为什么这是“无效的C ++”

时间:2011-08-16 16:51:39

标签: c++

我正在阅读关于gtest的介绍并发现这部分令人困惑:

  

编译器抱怨某些静态的“未定义引用”   const成员变量,但我确实在类体中定义它们。   怎么了?

     

如果您的班级有静态数据成员:

// foo.h
class Foo {
  ...
  static const int kBar = 100;
};
     

您还需要在foo.cc中的类主体之外定义它:

const int Foo::kBar;  // No initializer here.
     

否则您的代码无效的C ++ ,并且可能会意外中断   方法。特别是在Google Test比较断言中使用它   (EXPECT_EQ等)将生成“未定义的引用”链接器错误。

有人可以解释为什么在类中定义静态const而不在类体外定义它是非法的C ++?

3 个答案:

答案 0 :(得分:5)

首先,在类体内部不是定义,它是一个声明。声明指定常量的类型和值,该定义保留存储空间。您可能不需要存储空间,例如,如果您仅将该值用作编译时常量。在这种情况下,您的代码是完全合法的C ++。但是如果你做的事情就像通过引用传递常量,或者使指针指向常量那么你也需要存储。在这些情况下,您会收到“未定义的引用”错误。

答案 1 :(得分:3)

标准基本上表明即使你可以在标题中给出一个值,如果静态变量被“使用”,你必须仍然在源文件中定义它。

在此上下文中,“used”通常被理解为表示程序的某些部分需要实际内存和/或变量的地址。

谷歌测试代码很可能在某个时刻获取变量的地址(或以其他一些等效的方式使用它)。

答案 2 :(得分:2)

粗略地说:在类定义中,static const int kBar = 100;告诉编译器“Foo将有一个kBar常量(我保证永远为100)”。但是,编译器不知道该变量的位置。在foo.cc文件中,const int Foo::kBar;告诉编译器“好吧,在这个地方制作kBar”。否则,链接器会寻找kBar,但无法在任何地方找到它。