正确答案是肯定的,一个类的名字可能有外部链接。以前的答案是错误的和误导性的。您显示的代码是合法且常见的。
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 提供的 Wikipedia 链接甚至将其声明为一个例外。
有些东西,比如类型、模板和外部内联函数,可以在多个翻译单元中定义。对于给定的实体,每个定义必须相同。
ODR 规则将内容考虑在内。实际上,您显示的内容是翻译单元将类用作完整类型所必需的。
§3.5 [basic.def.odr]
如果以要求类类型完整的方式使用类,则翻译单元中需要类的确切定义。
编辑 - James Kanze 回答的后半部分是正确的。