【问题标题】:Why is there no multiple definition error when you define a class in a header file?为什么在头文件中定义类时没有多重定义错误?
【发布时间】:2013-01-17 05:48:51
【问题描述】:

我不确定我是否正确地问了这个问题,但让我解释一下。

首先,我阅读了这篇解释声明和定义之间区别的文章: http://www.cprogramming.com/declare_vs_define.html

其次,我从之前的研究中知道,在头文件中定义变量和函数是不好的做法,因为在链接阶段,您可能有多个同名定义,这会引发错误。

但是,为什么课程不会发生这种情况?根据另一个SO答案( What is the difference between a definition and a declaration? ),下面是一个类定义:

    class MyClass {
        private:
        public:
    };

如果上述定义在头文件中。然后,据推测,您可以拥有多个 #include 该标头的 .cpp 文件。这意味着在多个 .o 文件中编译后多次定义该类,但似乎不会造成太大问题...

另一方面,如果它是在头文件中定义的函数,显然会导致问题...据我了解...也许?

那么类定义有什么特别之处呢?

【问题讨论】:

  • 你的头文件有头保护吗?
  • 确实如此。但是,据我了解,标头保护只能防止同一源文件中的多个定义(stackoverflow.com/questions/2216765/…)。此问题主要与包含相同标头的多个源文件的情况有关。

标签: c++ linker header-files one-definition-rule


【解决方案1】:

您的类定义定义了该类,但没有定义该类的对象。可以在多个文件中定义类(或结构),因为您只是定义了一个 type,而不是该类型的变量。如果您只有定义,编译器将不会发出任何代码。
编译器实际上只有在您声明了这种类型的对象(即变量)后才会发出代码:

class MyClass myvar;

或:

class MyOtherClass { 
    public: ...
    private: ...
} myvar;         // note the variable name, it instantiates a MyOtherClass

这是您不希望在标头中执行的操作,因为它会导致 myvar 的多个实例被实例化。

【讨论】:

  • 我不喜欢这个答案,因为也可以为函数声明类似的论点:“函数定义定义了一个函数,但没有调用它。”!
【解决方案2】:

单一定义规则(3.2,[basic.def.odr])以不同的方式应用于类和函数:

1 - 任何翻译单元不得包含多个变量、函数、类类型、枚举类型或模板的定义。

[...]

4 - 每个程序都应包含该程序中 odr 使用的每个非内联函数或变量的准确定义 [...]

因此,虽然(非内联)函数在整个程序中最多可以定义一次(如果它们被调用或以其他方式使用,则只能定义一次),类可以定义与翻译单元一样多的次数(源文件),但每个翻译单元不超过一次。

这样做的原因是因为类是类型,它们的定义对于能够在翻译单元之间共享数据是必要的。最初,类(C 中的structs)没有任何需要链接器支持的数据; C++ 引入了虚成员函数和虚继承,这需要 vtable 的链接器支持,但这通常通过将 vtable 附加到成员函数(的定义)来解决。

【讨论】:

    【解决方案3】:

    类定义只是该类对象的一种蓝图。自 C 日以来,struct 一直如此。代码中实际上不存在任何类或结构。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-28
      • 1970-01-01
      相关资源
      最近更新 更多