Правильный ответ - да, имя класса может иметь внешнюю связь.Предыдущие ответы неверны и вводят в заблуждение.Код, который вы показываете, является законным и распространенным.
Имя класса в C ++ 03 может иметь внешнюю связь или не иметь связи.В C ++ 11 имя класса может дополнительно иметь внутреннюю связь.
C ++ 03
§3.5 [basic.link]
Имяговорят, что имеет связь, когда она может обозначать тот же объект, ссылку, функцию, тип , шаблон, пространство имен или значение в качестве имени, введенного объявлением в другой области действия
Классимена могут иметь внешнюю связь.
Имя, имеющее область имен, имеет внешнюю связь, если это имя
[...]
- именованный класс(раздел 9) или безымянный класс, определенный в объявлении typedef, в котором класс имеет имя typedef для целей связывания (7.1.3)
Имена классов не могут иметь связи.
Имена, на которые не распространяются эти правила, не имеют связи.Кроме того, за исключением отмеченного, имя, объявленное в локальной области (3.3.2), не имеет связи.Имя без связи (в частности, имя класса или перечисления, объявленного в локальной области (3.3.2)) не должно использоваться для объявления объекта со связью.
В C ++11 изменения первой кавычки и имена классов в области пространства имен теперь могут иметь внешнюю или внутреннюю связь.
Пространство имен без имени или пространство имен, объявленное прямо или косвенно в пространстве имен без имени, имеет внутреннюю связь.Все остальные пространства имен имеют внешнюю связь.Имя, имеющее область имен, которому не было присвоено внутреннее связывание выше [именами классов не было], имеет ту же связь, что и окружающее пространство имен, если это имя
[...]
- именованный класс (раздел 9) или безымянный класс, определенный в объявлении typedef, в котором класс имеет имя typedef для целей связывания (7.1.3);
Вторая цитата также изменяется, новывод тот же, имена классов могут не иметь связи.
Имена, не охваченные этими правилами, не имеют связи.Кроме того, за исключением отмеченного, имя, объявленное в области видимости блока (3.3.3), не имеет связи.Говорят, что тип имеет связь в том и только в том случае, если:
- это тип класса или перечисления, который назван (или имеет имя для целей связывания (7.1.3)), а имя имеет связь;или
- это неназванный член класса или перечисления класса со связью;
Некоторые ответы здесь объединяют абстрактное понятие связи в Стандарте C ++ с компьютерной программойизвестный как линкер.Стандарт C ++ не придает особого значения символу слова.Символ - это то, что компоновщик разрешает при объединении объектных файлов в исполняемый файл.Формально это не имеет отношения к понятию связи в Стандарте C ++.В документе только когда-либо упоминаются компоновщики в сноске, касающейся кодировки символов.
Наконец, ваш пример является допустимым C ++, а не является нарушением ODR .Рассмотрим следующее.
C.h
----------
class w
{
public:
w();
};
A.cpp
-----------
#include "C.h"
B.cpp
-----------
#include "C.h"
Возможно, это выглядит знакомым.После того, как директивы препроцессора оценены, мы остаемся с оригинальным примером.Ссылка на Википедию, предоставляемая Alok Save, даже утверждает это как исключение.
Некоторые вещи, такие как типы, шаблоны и внешние встроенные функции, могут быть определены в нескольких единицах перевода.Для данного объекта каждое определение должно быть одинаковым.
Правило ODR учитывает содержание.То, что вы показываете, на самом деле требуется для того, чтобы единица перевода могла использовать класс в качестве завершенного типа.
§3.5 [basic.def.odr]
Ровно одно определениекласс требуется в единице перевода, если этот класс используется таким образом, что тип класса должен быть завершен.
правка - Вторая половина ответа Джеймса Канзе правильно поняла.