带有非模板库的模板类给出了LNK2005错误

时间:2011-03-22 18:14:11

标签: c++ templates inheritance lnk2005

我有一个模板类 Child ,它继承自非模板 Parent 类。当我在多个.cpp文件中包含 Child 的标头时,我收到LNK2005错误。发生这种情况是因为 Parent 在多个编译单元中定义。当这些单元链接在一起时,它们会导致LNK2005错误。

如果您想知道,的目的是为所有 Child 实例提供 Child 一个静态变量,而不只是一个对于每个孩子< ''输入''>

我的问题是,如何创建一个具有唯一(跨所有 Child 实例)静态变量的模板化类,并且可以包含在多个.cpp文件中?

这是一个导致LNK2005错误的玩具示例:

的main.cpp

#include "Apple.h"
#include "Banana.h"

#include <string>

void main() {
    Apple apple;
    Banana banana;
}

Apple.h

#ifndef APPLE_H
#define APPLE_H

struct Apple {
    Apple();
};

#endif // APPLE_H

Apple.cpp

#include "Apple.h"
#include "Child.h"

Apple::Apple() {
    Child<int> child;
    child.foo(5);
}

Banana.h

#ifndef BANANA_H
#define BANANA_H

struct Banana {
    Banana();
};

#endif // BANANA_H

Banana.cpp

#include "Banana.h"
#include "Child.h"

Banana::Banana() {
    Child<double> child;
    child.foo(3.14);
}

Child.h

#ifndef CHILD_H
#define CHILD_H

#include <iostream>

using namespace std;

///////////// Parent Class Def ///////////

class Parent {
    protected:
    static int id;
};

int Parent::id = 0;

///////////// Child Class Def ///////////

template <class T>
struct Child : protected Parent {
    Child();
    void foo(T t);
};

template <class T>
Child<T>::Child() {
    id++;
}

template <class T>
void Child<T>::foo(T t) {
    cout << "Child" << id << "'s foo() says: " << t << endl;
}

#endif // CHILD_H

错误LNK2005:已在Apple.obj中定义的“protected:static int Parent :: id”(?id @ Parent @@ 1HA)

2 个答案:

答案 0 :(得分:6)

您需要在int Parent::id = 0;中定义一次Child.C。通过将其包含在标题中,每个包含标题的文件都会定义一次。

我想我应该注意,在将它放入Parent.C(匹配的类名)或Child.C匹配标题名称的邪恶之间,我选择了一致性。更好的方法是将Parent放在自己的文件中,这样就可以将定义放在一个恰当名称的Parent.C中,它仍然与相应的标题名称相匹配。

答案 1 :(得分:1)

拉​​

int Parent::id = 0;

进入Parent.cpp,你会没事的。现在发生的事情是,每个包含Child.h的翻译单元都会包含一次定义。