2

テンプレート化されていない親クラスから継承するテンプレート化されたクラスChildがあります。複数の .cpp ファイルにChildのヘッダーを含めると、LNK2005 エラーが発生します。これは、が複数のコンパイル単位で定義されるために発生します。これらのユニットが一緒にリンクされると、LNK2005 エラーが発生します。

ご参考までに、Parentの目的は、 Child< ''type'' >ごとに 1 つだけでなく、すべてのChildインスタンスに対して 1 つの静的変数を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);
}

バナナ.h

#ifndef BANANA_H
#define BANANA_H

struct Banana {
    Banana();
};

#endif // BANANA_H

バナナ.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:「保護: static int Parent::id」(?id@Parent@@1HA) は Apple.obj で既に定義されています

4

2 に答える 2

6

int Parent::id = 0;で一度だけ定義する必要がありますChild.C。ヘッダーに含めることで、ヘッダーを含むファイルごとに 1 回定義されます。

Parent.Cそれを入れること(クラス名の一致)またはChild.Cヘッダー名の一致の悪の間で、私は一貫性を選んだことに注意する必要があると思います。対応するヘッダー名と一致Parentする適切な名前で定義を配置できるように、独自のファイルを配置することをお勧めします。Parent.C

于 2011-03-22T18:16:17.210 に答える
1

Pull

int Parent::id = 0;

out into Parent.cpp and you 'll be fine. What happens now is that the definition gets included once per translation unit that includes Child.h.

于 2011-03-22T18:17:06.750 に答える