【问题标题】:Why does a static data member need to be defined outside of the class?为什么需要在类之外定义静态数据成员?
【发布时间】:2013-09-11 18:53:54
【问题描述】:

根据 IBM C++ 知识中心的Static data members

类成员列表中静态数据成员的声明不是定义。您必须在类声明之外,在命名空间范围内定义静态成员。

这是为什么呢?关于内存分配的原理是什么?

【问题讨论】:

  • 我自己一直想知道这一点。它总是“似乎”像标题一样是定义静态的更合适的地方。
  • @koodawg Java 结合了标头 + 源代码实现 =]
  • 原因是一个类可能在许多翻译单元中被声明(通过#include),如果在所有翻译单元上都定义了它,就会有一个重复的符号。
  • 静态类成员具有外部链接,并且必须遵守对该模型的限制,只有一个定义。随着编译器变得更聪明,也有例外(static const 积分成员)。如果它有帮助,请将它们视为全球extern decl,其中必须有一个定义来满足该法案。

标签: c++ static


【解决方案1】:

这是一种语言规则,被称为一个定义规则。在程序中,每个静态对象(如果使用的话)都必须定义一次,而且只能定义一次。

类定义通常放在头文件中,包含在多个翻译单元中(即来自多个源文件)。如果标题中的静态对象声明是一个定义,那么您最终会得到多个定义,每个包含标题的单元中都有一个定义,这会违反规则。因此,它不是一个定义,您必须在其他地方准确提供一个定义。

原则上,语言可以做它对内联函数所做的事情,允许将多个定义合并为一个定义。但事实并非如此,所以我们坚持这条规则。

【讨论】:

  • 为了完整起见,可能需要提及内联静态和 constexpr 静态成员
【解决方案2】:

这根本与内存分配无关。这是关于在链接的编译单元中具有单点定义。 @Nick 也指出了这一点。

来自 Bjarne 的网站https://www.stroustrup.com/bs_faq2.html#in-class

一个类通常在头文件中声明,而头文件是 通常包含在许多翻译单元中。然而,为了避免 复杂的链接器规则,C++ 要求每个对象都有唯一的 定义。如果 C++ 允许在课堂上,这条规则就会被打破 定义需要作为对象存储在内存中的实体。

【讨论】:

    【解决方案3】:

    从 C++17 开始,您现在可以在类中定义静态数据成员。见cppreference

    静态数据成员可以内联声明。内联静态数据 成员可以在类定义中定义,并且可以指定一个 初始化器。它不需要类外定义:

    struct X {
         inline static int n = 1; 
    };
    

    【讨论】:

      猜你喜欢
      • 2012-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多