0

数日間、Code::Blocks IDE (Linux、Ubuntu 64 ビット) を使用して、C++ で記述された 1 つのプロジェクトをコンパイルしようとしています。コードは有効ですが、リンカー エラーがいくつかあります。クラスでインライン定義されておらず、他のファイルにある関数に対して「未定義の参照」というエラーが発生することに気付きました (クラスは i *.h ファイルで、これらの関数の定義は *.cpp にあります)。独自の Makefile を作成しようとしましたが、役に立ちませんでした。

メイクファイル:

all: project

project: main.o DList.o Person.o
    g++ main.o DList.o Person.o -o project

main.o: main.cpp
    g++ -c main.cpp

DList.o: include/DList.cpp
    g++ -c include/DList.cpp

Person.o: include/Person.cpp
    g++ -c include/Person.cpp

clean:
    rm -rf *.o

ネットでこれらのエラーについていくつか読んだのですが、どうすればよいかわかりません。

// 編集 Object.cpp と Object.h を Person.cpp と Person.h に変更し、*.cpp ファイルをメイン ディレクトリに移動し、*.cpp ファイルの #include パスを変更しました。

エラー:

obj/Debug/main.o||In function `main':|
...main.cpp|19|undefined reference to `DListIterator<Person>::go(int)'|
...main.cpp|20|undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <Person>(std::basic_ostream<char, std::char_traits<char> >&, DList<Person>&)'|
...main.cpp|21|undefined reference to `DList<Person>::~DList()'|
...main.cpp|21|undefined reference to `DList<Person>::~DList()'|
obj/Debug/main.o||In function `DList<Person>::insert(Person&)':|
...include/DList.h|45|undefined reference to `DList<Person>::insert(Person&, DListIterator<Person>&)'|
||=== Build finished: 5 errors, 0 warnings ===|

コマンド ラインで make を開始してビルドするか、Code::Blocks で Build 関数を使用してビルドするかに違いはありません。

すべてのコードを *.cpp ファイルから *.h ファイルにコピーしたとき、コンパイラはエラーを返さなかったので、リンカの問題だけだと思います。

4

1 に答える 1

4

テンプレートを個別にコンパイルしようとしているようです。DList.cppテンプレートは使用時にのみインスタンス化され、ファイルで使用されることはないため、これは一般的に不可能です。次の 2 つのいずれかを試してください。

  • 関数の定義をDListヘッダー ファイルに移動します (これは通常の方法です)。
  • のいくつかの明示的なインスタンス化をDListファイルにDList.cpp入れます。(例: template class DList<Person>;)

問題の完全な例: 現在、次のものがあります。

//DList.h
template<typename T>
class DList {
    void insert(T& newPerson);
    //etc
};

//DList.cpp
#include "DList.h"
//The when this is being compiled, 
//the compiler does not know about Person,
//so it cannot instantiate this function.
template<typename T>
void DList<T>::insert(T& newPerson) {
    //implementation
}
//etc

//main.cpp
#include "DList.h"
#include "Person.h"
int main() {
    //When this is being compiled, it does not know the
    //definition of the out-of-line functions in `DList`,
    //so it cannot instantiate them.
    DList<Person> people;
    people.insert(Person("Joe"));
}

考えられる修正の 1 つはDList.cpp、定義を削除して "DList.hpp" に入れることです。

//DList.hpp
template<typename T>
class DList {
    void insert(T& newPerson) {
        //implementation
    }
    ~DList();
    //etc
};
//the implementations can alternatively be
//placed outside the class, but in the header:
template<typename T>
DList<T>::~DList() {
    //implementation
}

もう1つの修正は、明示的にインスタンス化することですDList(定義が利用可能なコンパイルユニットで):

//DList.cpp
#include "DList.h"
#include "Person.h"
template<typename T>
void DList<T>::insert(T& newPerson) {
    //implementation
}
//Explicit instantiation:
template class DList<Person>;
于 2012-08-28T07:50:16.297 に答える