对静态类成员的未定义引用

任何人都可以解释为什么下面的代码不会编译 至less在g ++ 4.2.4上。

而更有趣的是,为什么在我将MEMBER转换为int时会编译?

#include <vector> class Foo { public: static const int MEMBER = 1; }; int main(){ vector<int> v; v.push_back( Foo::MEMBER ); // undefined reference to `Foo::MEMBER' v.push_back( (int) Foo::MEMBER ); // OK return 0; } 

您需要实际定义静态成员(在类定义之后)。 尝试这个:

 class Foo { /* ... */ }; const int Foo::MEMBER; int main() { /* ... */ } 

这应该摆脱未定义的参考。

问题来自于新的C ++特性的一个有趣的冲突,以及你正在尝试做什么。 首先,我们来看一下push_back签名:

 void push_back(const T&) 

期待对T型对象的引用。 在旧的初始化系统下,存在这样一个成员。 例如,下面的代码编译得很好:

 #include <vector> class Foo { public: static const int MEMBER; }; const int Foo::MEMBER = 1; int main(){ std::vector<int> v; v.push_back( Foo::MEMBER ); // undefined reference to `Foo::MEMBER' v.push_back( (int) Foo::MEMBER ); // OK return 0; } 

这是因为有一个实际的对象存储在那个值中。 但是,如果您切换到指定静态const成员的新方法(如上所述), Foo::MEMBER不再是一个对象。 这是一个常数,有点类似于:

 #define MEMBER 1 

但是没有预处理器macros的头痛(并且具有types安全性)。 这意味着期待参考的vector不能得到一个。

如果需要定义,C ++标准需要为你的静态const成员定义。

定义是必需的,例如,如果使用地址。 push_back通过const引用接受其参数,因此编译器需要使用成员的地址,并且需要在名称空间中定义它。

当你明确地转换常量时,你正在创build一个临时的,这是临时的,这是绑定到参考(在标准的特殊规则下)。

这是一个非常有趣的案例,我认为这是值得提出的问题,以便std被更改为对于常量成员具有相同的行为!

虽然以一种奇怪的方式,这可以被看作是一元运算符“+”的合法使用。 基本上, unary +的结果是一个右值,所以适用于rvalue绑定到const引用的规则,我们不使用我们的静态const成员的地址:

 v.push_back( +Foo::MEMBER ); 

Aaa.h

 class Aaa { protected: static Aaa *defaultAaa; }; 

Aaa.cpp

 // You must define an actual variable in your program for the static members of the classes static Aaa *Aaa::defaultAaa; 

不知道为什么演员工作,但Foo :: MEMBER不分配,直到第一次加载Foo,因为你永远不会加载,它永远不会被分配。 如果你在某个地方有一个Foo的参考,它可能会工作。

使用C ++ 11,以上对于基本types是可能的

 class Foo { public: static constexpr int MEMBER = 1; }; 

constexpr部分创build了一个静态expression式 ,而不是一个静态variables – 这就像一个非常简单的内联方法定义一样。 尽pipe如此,这个方法在模板类中用Cstring表示,有点不稳定。

关于第二个问题:push_ref作为一个参数引用,你不能有一个类/结构的静态常量的引用。 一旦你调用static_cast,就会创build一个临时variables。 并且可以传递这个对象的引用,一切正常。

或者至less我的同事谁解决这个如此说。