2012-03-28 4 views
7
//a.h 

extern int x1; 
static int x2; 
int x3; 
static const int x4; 

class A { 
    public: 
     static const int x5 = 10; 
}; 

a.h будет включен несколько .cpp файлов, на мой вопрос:`static`,` extern`, `const` в заголовочном файле

1. x1 это просто декларация, не так ли? Поэтому его определение должно быть сделано в одном из файлов .cpp, верно?

2. x2 - это определение, не так ли? Раньше я думал, что static int также является декларацией, как extern int, но я ошибся. x2 будет отображаться только в a.h?

3. будет определен несколько раз, если a.h включен в нескольких .cpp файлов, поэтому приведет к компиляции ошибки, не так ли?

4. x4 - это определение, не так ли?

5.Here в классе A, x5 является декларацией, да. Но как насчет x4?

+0

Что вы имеете в виду под вопросом в пункте 5? –

+0

@DavidHeffernan, я имею в виду, почему 'x5' является декларацией, но' x4'? – Alcott

ответ

10

1.x1 это просто декларация, не так ли? Поэтому его определение должно быть сделано в одном из этих файлов .cpp, правильно?

Правильная

2.x2 это определение, верно? Раньше я думал, что static int также является объявлением, как и extern int, но я ошибался. x2 будет видна только в a.h?

В каждой единицы перевода, которая включает заголовок, будет доступна другая x2.

3.x3 будет определен несколько раз, если a.h включен в несколько файлов .cpp, поэтому x3 приведет к ошибке компиляции, правильно?

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

4.x4 - это определение, верно?

Да, это определение, но, как x2 каждая единица перевода будет иметь свою собственную x4 (как из-за static и потому, что это constчто подразумевает внутреннюю связь

5.Here в классе А, x5 является декларацией, да. Но что х4?

Да, x5 это заявление только (инициализацию). путаница МИГ ht возникает потому, что ключевое слово static повторно используется для обозначения разных вещей в разных контекстах. В x5 это означает атрибут класса, в то время как в x4 это означает внутренней компоновкой

Этот последний случай является особенным. Это единственное объявление (IIRC), в котором объявление может иметь значение, и причина в том, что он позволяет компилятору использовать значение значение константы во всех единицах перевода, которые включают этот заголовок в качестве постоянной времени компиляции . Если значение должно быть обеспечено определением, то только одно переводное устройство будет иметь доступ к этому значению. Определение этого статического члена будет:

const int A::x5; // no initialization here 

И вы должны обеспечить один, если член ODR используемый. Теперь дело в том, что в большинстве случаев константа не будет odr-used, поскольку компилятор будет подставлять значение, когда используется выражение A::x5. Только тогда, когда элемент используется в качестве Lvalue вам нужно определение, например:

void f(const int &) {} 
int main() { 
    f(A::x5); 
} 

Поскольку аргумент f является ссылкой, использование A::x5 требует именующего (примечание, константный-Несс и lvalue/rvalue-ness почти ортогональны), и это требует определения члена в одной единице перевода в вашей программе.

+0

Что такое «внутренняя связь»? – Alcott

+0

@Alcott: Символ недоступен из-за пределов единицы перевода, в которой он определен. Это означает, что если несколько единиц перевода определяют символ с тем же именем с внутренней связью, каждая единица перевода получит свой собственный другой символ (т. Е. Разные символы, даже если они имеют одинаковое имя). –

4
  1. правильно

  2. Это определение, x2 будет 0, и каждый перевод блок, который содержит заголовок будет иметь свою собственную копию x2.

  3. Да, но это приведет к ошибке компоновщика, а не компилятору.

  4. То же, что и 2., но вы не можете изменить его.

  5. Внутри класса static имеет другое значение. Это законно только потому, что x5 имеет встроенный тип const, который также инициализируется.

+0

Итак, 'x2' не является глобальным var, который может быть разделен между несколькими файлами' .cpp'? – Alcott

+0

@LuchianGrigore: в одной единице перевода вы определяете его как 'const int A :: x5;' (в определении не разрешено инициализация). Если вы хотите проверить, что это не определение, добавьте в программу: 'void f (const int &) {} int main() {f (A :: x5); } ', и вы получите ошибку компоновщика (пока вы не добавите определение). –

+0

@Alcott no, x2 будет отличаться для каждого файла 'cpp'. –