0

これらは私のファイルです:

-------- [c.hpp] --------

#ifndef _C
#define _C

#include<iostream>
class C
{
public:
    template<class CARTYPE> void call(CARTYPE& c);
};

#endif

-------- [c.cpp] --------

#include "c.hpp"

template<class CARTYPE> void C::call(CARTYPE& c)
{
    //make use of c somewhere here
    std::cout<<"Car"<<std::endl;
}

-------- [v.cpp] --------

class Merc
{};

-------- [main.cpp] --------

#include "c.hpp"
#include "v.cpp"
//#include "c.cpp"

int main()
{
    Merc m; 
    C someCar;
    someCar.call(m);

}//main

コマンドg++-cmain.cppおよびg++-c c.cppなどを使用して、上記のすべてのファイルに対して「.o」ファイルを生成できます。しかし、「。o」ファイルをg ++ -o car co main.o voにリンクしようとすると、次のエラーが発生します。

main.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `void C::call<Merc>(Merc&)'
collect2: ld returned 1 exit status

main.cppの#include"c.cpp"のコメントを外すとエラーはなくなりますが、この方法でcppファイルを含めるのは悪い習慣かもしれません。私はこれを間違っていますか?個別のオブジェクトファイルを作成してそれらをリンクしながら、テンプレート化された宣言に対応するためのより良い方法はありますか?ps:私ははるかに複雑なクラス構造でテンプレート化された関数を使用しています。ここに示されているのは、私が直面しているエラーの種類を示すためのほんの小さな例です。

4

3 に答える 3

2

これは、コンパイル時c.cppにコンパイラがのコードを生成する必要があることを認識しておらず、コンパイル時にインスタンス化元の定義がないためC::call<Merc>(Merc&)だと思います。main.cppC::call<T>(T&)C::call<Merc>(Merc&)

テンプレート定義は本質的にセマンティックマクロであるため、プリプロセッサのレキシカルマクロと同様に、#defineそれらを使用するコンパイルユニットで表示される必要があります。

于 2010-10-07T05:24:57.550 に答える
1

この問題を解決する方法は次のとおりです。

a。c.cppから'#include"c.hpp"'を削除しますAND

b。'c.hpp'の最後に'c.cpp'を含めます(奇妙な響きの'#include "c.pp"')

このようにして、テンプレート定義は、各.cppファイルで明示的に行わなくても、「c.hpp」を含む各変換ユニットで使用できます。これは「包含モデル」と呼ばれます

于 2010-10-07T05:27:10.597 に答える
0

基本的に、現在のC ++では、関連するテンプレート宣言と定義を別々のファイルに含めることはできません。1つのファイルでクラスCを完全に定義する必要があります。

于 2010-10-07T05:44:52.510 に答える