提问者:小点点

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


有人能解释为什么下面的代码不能编译吗?至少在G++4.2.4上。

更有趣的是,为什么当我将成员强制转换为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;
}

共3个答案

匿名用户

null

class Foo { /* ... */ };

const int Foo::MEMBER;

int main() { /* ... */ }

null

匿名用户

这个问题的出现是因为新的C++特性和你想要做的事情发生了有趣的冲突。首先,我们来看看push_back签名:

void push_back(const T&)

null

#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;
}

null

#define MEMBER 1

null

匿名用户

null

定义是必需的,例如,如果使用它的地址。push_back通过常量引用获取参数,因此严格地说,编译器需要成员的地址,您需要在名称空间中定义它。

当您显式强制转换常量时,您正在创建一个临时的,并且这个临时的绑定到引用(根据标准中的特殊规则)。

这是一个非常有趣的案例,我实际上认为值得提出一个问题,以便将std改变为有相同的行为为您的固定成员!

不过,以一种奇怪的方式,这可以被看作是一元'+'运算符的合法使用。基本上,一元+的结果是一个rvalue,因此将rvalue绑定到const引用的规则适用,我们不使用静态const成员的地址:

v.push_back( +Foo::MEMBER );