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 почти ортогональны), и это требует определения члена в одной единице перевода в вашей программе.
Что вы имеете в виду под вопросом в пункте 5? –
@DavidHeffernan, я имею в виду, почему 'x5' является декларацией, но' x4'? – Alcott