为什么允许在几个cpp文件中重新定义类

8 c++ class definition

让我有两个cpp文件:

//--a.cpp--//
class A
{
public:
    void bar()
    {
        printf("class A");
    }
};
//--b.cpp--//
class A
{
public:
    void bar()
    {
        printf("class A");
    }
};
Run Code Online (Sandbox Code Playgroud)

当我正在编译并将这些文件链接在一起时,我没有错误.但如果我写下以下内容:

//--a.cpp--//
int a;
//--b.cpp--//
int a;
Run Code Online (Sandbox Code Playgroud)

在编译和链接这些源代码后,我发现了一个错误,因为它的重新定义a.但是在我重新定义类的情况下,但没有引发错误.我糊涂了.

das*_*ght 11

类是类型.在大多数情况下,它们是编译时的工件; 另一方面,全局变量是运行时工件.

在您的第一个示例中,每个翻译单元都有自己的定义class a.由于翻译单元彼此分开,并且因为它们不会产生具有相同名称的全局运行时工件,所以这是可以的.该标准要求每个翻译单元只有一个类的定义 - 见3.2.1和3.2.4节:

任何翻译单元都不得包含任何变量,函数,类类型,枚举类型或模板的多个定义.

如果以需要类类型完整的方式使用类,则在翻译单元中需要一个类的正确定义.

但是,该标准允许在单独的翻译单元中进行多个类定义 - 请参阅第3.2.6节:

类类型,枚举类型,具有外部链接的内联函数,类模板,非静态函数模板,类模板的静态数据成员,类模板的成员函数或模板特化可以有多个定义如果每个定义出现在不同的翻译单元中,并且定义满足以下要求,则程序中未指定某些模板参数.[...]

以下是一长串要求,归结为两个类定义必须相同; 否则,该计划被认为是不正确的.

在第二个示例中,您将int a在两个转换单元中定义全局运行时工件(变量).当链接器尝试生成最终输出(可执行文件或库)时,它会找到这两个输出,并发出重定义错误.请注意,上面的规则3.2.6不包括具有外部链接的变量.

如果声明变量static,程序将编译,因为静态变量是定义它们的转换单元的本地变量.

虽然两个程序都可以编译,但它们编译的原因是不同的:在多个类定义的情况下,编译器假定这两个类是相同的; 在第二种情况下,编译器认为这两个变量彼此独立.