static const int成员和未定义的引用

时间:2013-07-03 14:31:53

标签: c++ gcc c++11 linker static-members

我使用gcc 4.7.3 for ARM平台来编译我的代码。我有几个这样的课程:

// types.h
enum Types
{
    kType1,
    kType2
    // ...
};

// d1.h
class D1 : public Base
{
public:
    static const int type = kType1;
    // ...
};

// d2.h
class D2 : public Base
{
public:
    static const int type = kType2;
    // ...
};

我使用这些类的源代码中的某处:

MyObject obj;
doSomething<D1>(obj);
doSomething<D2>(obj);

// other.cpp
class Foo
{
    template<typename T>
    void doSomething(MyObject obj)
    {
        mm_.insert(std::multimap<int, MyObject>::value_type(T::type, obj));
    }
};

获取下一条消息(在链接期间):

undefined reference to `D1::kType`
undefined reference to `D2::kType`
// more messages of this type

行。如果我像这样更改do_something函数:

template<typename T>
void doSomething(MyObject obj)
{
    mm_.insert(std::multimap<int, MyObject>::value_type( (int) T::type, obj));
}

它编译好了。但为什么?关于它的标准找不到任何东西。有没有人对正在发生的事情有所了解?

感谢。

P.S。

此修复

 // d1.cpp
 const int D1::kType;

也有效,但这是预期的。

P.P.S。在使用引用或指向T :: type的情况下,答案是非常明显的,但我没有看到任何需要ref或ptr的东西。 AFAIK std :: multimap :: value_type按值(不是ref,也不是ptr)获取参数。

1 个答案:

答案 0 :(得分:1)

// d1.cpp
const int D1::kType;

// d2.cpp
const int D2::kType;

就是答案,

//d1.h
public:
    static const int type = kType1;

就像一个函数原型,它被编译到包含头的每个复杂对象(cpp文件)中,因此由于ODR规则它实际上不保留内存空间,否则链接器会发现很多每个编译单元中包含标题的变量实例。

因此,您需要一个编译单元(一个cpp文件),它定义将用于多次使用的标头中找到的类常量的实际内存空间。