Как компилятор может различать статические элементы данных с одинаковыми именами в разных классах C++?

Недавно у меня было интервью по C++, где меня спросили, как компилятор различает статические элементы данных с одинаковыми именами в двух разных классах?

Поскольку все статические переменные данных хранятся в сегменте данных, должен быть способ, с помощью которого компилятор отслеживает, какие статические данные принадлежат какому классу, особенно если они имеют одно и то же имя.

Редактировать: я ответил на изменение имени, но он отказался сказать, что изменение имени используется только среди членов одного класса.


person San    schedule 04.10.2010    source источник
comment
Я так понимаю, вы не получили работу.   -  person Mark Ransom    schedule 04.10.2010
comment
Что ответил интервьюер?   -  person Thomas Matthews    schedule 04.10.2010
comment
@San: Ваш ответ был по существу правильным. Его ответ не имеет смысла. Возможно, для вас будет лучше, если вы не будете работать на него.   -  person Potatoswatter    schedule 04.10.2010
comment
Я подозреваю (но не могу сказать по информации, которую вы дали, или без разговора с интервьюером), что интервьюер пытался заставить вас говорить о префиксе имени класса а-ля A::foo против B::foo. Если да, то вопрос был задан плохо, и он дал вам плохие подсказки.   -  person Andrew Shelansky    schedule 04.10.2010
comment
Что же, он сказал, был метод? В некоторых случаях это определенно искажение имен, хотя это не обязательно.   -  person Jon Hanna    schedule 04.10.2010
comment
Он не дал мне никакого ответа, он продолжал задавать другие вопросы   -  person San    schedule 04.10.2010


Ответы (8)


Имена искажены с их именем класса в них. Пример с компилятором clang

class A {
  static int i;
};

int A::i = 0;

Вывод

$ clang++ -cc1 -emit-llvm main1.cpp -o -
; ModuleID = 'main1.cpp'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
target triple = "i386-pc-linux-gnu"

@_ZN1A1iE = global i32 0, align 4

Где _ZN1A1iE

$ c++filt _ZN1A1iE
A::i
person Johannes Schaub - litb    schedule 04.10.2010

Это определяется реализацией, поэтому нет единого способа сделать это.

Однако часто используется изменение имен.

person Jon Hanna    schedule 04.10.2010

Ну, я бы предположил, что из-за искажения имени имя класса также кодируется с данными. Я не удивлюсь, если это так же просто, как префикс имени:

class one
{
   static int data;
};

class two
{
   static int data;
};

могут быть имена

one::data
two::data

в сегменте данных. Это уникальные имена.

person miked    schedule 04.10.2010
comment
Я тоже сказал об изменении имени, но он отказался сказать, что изменение имени используется для различения членов одного и того же класса. - person San; 04.10.2010

Имя — это просто то, что люди используют для придания значения вещам.

Как только компилятор узнает, что это разные элементы (поскольку они объявлены в разных классах), он не будет использовать имя, чтобы различать их внутри двоичного файла, он будет использовать указатели, а указатели не заботятся об именах :)

Тогда ничто не запрещает добавлять перед именем данных закрывающий класс.

person Jack    schedule 04.10.2010

Все ответы на "изменение имен" касаются того, как отладчик находит хранилище для каждого символа и как компоновщик узнает разницу, но компилятор знает, потому что эти сущности занимают разные записи в таблице символов.

Вот и все.

Исполняемому файлу вообще не нужно ничего знать об именах{*}. Просто локации. Компилятор знает об именах, и эти знания закодированы в таблице символов (как бы это ни было реализовано).

{*} Ну, во всяком случае, при отсутствии RTTI.

person dmckee --- ex-moderator kitten    schedule 04.10.2010
comment
Статические члены класса, в отличие от статических глобальных, имеют внешнюю связь. Таким образом, компоновщик должен сопоставлять их по имени, а с динамическими библиотеками - также и загрузчик. Только компилятор знает, что на самом деле означают искаженные имена, но компоновщик и загрузчик также используют их. - person Ben Voigt; 04.10.2010
comment
@Бен. да. Я согласен. Та же мысль пришла мне в голову после того, как я отошел от компьютера на обед. Тем не менее, я придерживаюсь позиции, что знание различий лежит в таблице символов: искажение имен — это просто сериализация фундаментального различия в том, что это разные символы. - person dmckee --- ex-moderator kitten; 04.10.2010
comment
Правильно. Мой комментарий скорее уточнение, чем несогласие. - person Ben Voigt; 05.10.2010
comment
+1 Думаю, стоит пояснить, что области видимости переменных различаются. Это не просто разные записи, свободно плавающие в пустоте. Компилятор помещает каждый в свою область действия - будь то объединение его элементов или построение дерева. - person Tony Delroy; 05.10.2010

Имя класса уточняет имя члена: myclass::mymemb. Компилятор различает их так же, как и вы, когда ссылаетесь на них вне класса.

В реализации это делается путем изменения имени; компилятор очищает имя класса и имя члена и связывает их вместе в беспорядок, такой как __i_7myclass_6mymemb.

Процесс изменения имени (или его необходимость) является причиной, по которой нам нужен extern "C" для совместимости с интерфейсами C, которые определяют неизменяемые имена.

person Potatoswatter    schedule 04.10.2010

Имена static членов класса будут искажены таким образом, что имя класса будет частью «глобального» имени, видимого компоновщику.

person Michael Burr    schedule 04.10.2010

Он прикрепляет имя класса к имени члена данных. (А потом коверкает все это имя.)

person Jim Buck    schedule 04.10.2010