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

任何人都可以解释为什么下面的代码不会编译? 至少在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;
}

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

#define MEMBER 1

但没有预处理器宏的头痛(并且具有类型安全性)。 这意味着期待参考的矢量不能得到一个。


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

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

当你明确地转换常量时,你正在创建一个临时参数,并且这是临时参数(根据标准中的特殊规则)。

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

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

v.push_back( +Foo::MEMBER );
链接地址: http://www.djcxy.com/p/72269.html

上一篇: Undefined reference to static class member

下一篇: Why should exceptions be used conservatively?