Undefined reference to static class member
有人能解释一下为什么下面的代码不能编译吗?至少在G++4.2.4上。
更有趣的是,当我将成员强制转换为int时,它为什么要编译?
1 2 3 4 5 6 7 8 9 10 11 12 13 | #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; } |
您需要在某个地方(在类定义之后)实际定义静态成员。试试这个:
1 2 3 4 5 | class Foo { /* ... */ }; const int Foo::MEMBER; int main() { /* ... */ } |
这应该消除未定义的引用。
问题是因为新的C++特性和你想做的事情发生了一个有趣的冲突。首先,让我们看一下
1 | void push_back(const T&) |
它期望引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #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; } |
这是因为有一个实际的对象在某个地方存储了该值。但是,如果您像上面那样切换到指定静态常量成员的新方法,那么
1 | #define MEMBER 1 |
但是没有预处理器宏的麻烦(也没有类型安全)。这意味着期望引用的向量不能得到一个。
如果需要某种定义,C++标准需要为静态const成员定义一个定义。
例如,如果使用了地址,则需要定义。
当您显式地强制转换常量时,您将创建一个临时的,并且它是绑定到引用的临时的(根据标准中的特殊规则)。
这是一个非常有趣的案例,我实际上认为值得提出一个问题,这样性病就可以被改变为对你的常任会员同样的行为!
尽管如此,以一种奇怪的方式,这可以被视为一元"+"运算符的合法使用。基本上,
1 | v.push_back( +Foo::MEMBER ); |
AA. H
1 2 3 4 5 6 7 | class Aaa { protected: static Aaa *defaultAaa; }; |
美国石油协会
1 2 3 | // 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,上面的基本类型是可能的。
1 2 3 4 | class Foo { public: static constexpr int MEMBER = 1; }; |
关于第二个问题:push_-ref将引用作为参数,并且不能引用类/结构的静态const memeber。一旦调用static_cast,就会创建一个临时变量。可以传递对这个对象的引用,一切都正常。
或者至少我解决这个问题的同事这么说。