1

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

// 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));
}

它编译好。但为什么?在标准中找不到任何关于它的内容。有人对发生的事情有想法吗?

谢谢。

附言

此修复

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

也有效,但这是意料之中的。

PPS 如果使用指向 T::type 的引用或指针,答案将非常明显,但我看不到任何需要 ref 或 ptr 的东西。AFAIK std::multimap::value_type 按值获取参数(不是 ref,也不是 ptr)。

4

1 回答 1

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

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

是答案,

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

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

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

于 2013-09-20T12:19:16.767 回答