简体   繁体   English

具有非模板基的模板化类给我一个LNK2005错误

[英]Templated class with a non-template base gives me a LNK2005 error

I have a templated class Child which inherits from a non-templated Parent class. 我有一个模板类Child ,它从非模板的Parent类继承。 When I include Child 's header in multiple .cpp files I get a LNK2005 error. 当我在多个.cpp文件中包含Child的标头时,出现LNK2005错误。 This happens because Parent gets defined in multiple compilation units. 发生这种情况是因为Parent是在多个编译单元中定义的。 When those units get linked together they cause the LNK2005 error. 当这些单元链接在一起时,它们会导致LNK2005错误。

In case you're wondering, the purpose of Parent is to give Child one static variable for all Child instance, not just one for each Child< ''type'' > . 如果您想知道, Parent的目的是为Child提供一个静态变量给所有Child实例,而不仅仅是给每个Child <''type''>一个静态变量。

My question is, how do I create a templated class which has a unique (across all Child instances) static variable and can be included in multiple .cpp files? 我的问题是,如何创建一个具有唯一(在所有Child实例中)静态变量并且可以包含在多个.cpp文件中的模板化类?

Here's a toy example that causes this LNK2005 error: 这是导致此LNK2005错误的一个玩具示例:

main.cpp main.cpp中

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

#include <string>

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

Apple.h Apple.h

#ifndef APPLE_H
#define APPLE_H

struct Apple {
    Apple();
};

#endif // APPLE_H

Apple.cpp Apple.cpp

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

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

Banana.h Banana.h

#ifndef BANANA_H
#define BANANA_H

struct Banana {
    Banana();
};

#endif // BANANA_H

Banana.cpp Banana.cpp

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

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

Child.h 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

error LNK2005: "protected: static int Parent::id" (?id@Parent@@1HA) already defined in Apple.obj 错误LNK2005:Apple.obj中已定义的“保护:静态int Parent :: id”(?id @ Parent @@ 1HA)

You need to define int Parent::id = 0; 您需要定义int Parent::id = 0; just once in Child.C . Child.C只有一次。 By including it in the header it gets defined once per file that includes your header. 通过在标头中包含它,每个包含标头的文件都会被定义一次。

I suppose I should note that between the evils of putting it in Parent.C (matching class name) or Child.C matching the header name, I picked consistency. 我想我应该注意,在将其Child.C与标题名称匹配的Parent.C (匹配类名称)或Child.C的弊端之间,我选择了一致性。 Much better is to put Parent in its own files so that you can put the definition in an aptly named Parent.C which still matches the corresponding header name. 更好的方法是将Parent放在其自己的文件中,以便可以将定义放在适当命名的Parent.C ,该名称仍与相应的标头名称匹配。

Pull

int Parent::id = 0;

out into Parent.cpp and you 'll be fine. 进入Parent.cpp ,一切都会好起来的。 What happens now is that the definition gets included once per translation unit that includes Child.h . 现在发生的是,每个包含Child.h翻译单元都将定义包含一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM