1

標準出力から「データ」を傍受しようとしています(この質問では、coutを使用しています)。また、この質問では double を使用していますが、プログラムはプリミティブ データ型を処理できる必要があります。コードをコンパイルしようとすると、次のエラーが発生します。

「std::ostream& SpyOutput::operator<< (double const&)」への未定義の参照 collect2: エラー: ld が 1 つの終了ステータスを返しました

これが私のメインです:

    #include "SpyOutput.h"
    #define endl   '\n'
    int main ( int argc, char *argv[], char *env[] ) {
    double d1 = 12.3;
    SpyOutput spy(&cout);
    spy << d1;
    return 0;
    }

これは私のヘッダーファイルです:

#include <iostream>
using namespace std;

class SpyOutput {
private:
ostream* output;

public:
SpyOutput(ostream* os);
template <class T>
ostream &operator<<(const T &x);
};

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

#include "SpyOutput.h"
SpyOutput::SpyOutput(ostream* os){
output = os;
}

template <class T>
ostream& SpyOutput::operator<<(const T &x){
// SOME CODE GO HERE
return *output;
}

有効な解決策を見つけることなく、このエラー (および同様のエラー) をグーグル検索しました。:-)

4

2 に答える 2

2

どうしたの?

コンパイルされない理由については、「テンプレート クラスの定義をその宣言から分離して、.cpp ファイル内に配置できないのはなぜですか?」を参照してください。

例として、次のテンプレート関数宣言を含むヘッダー ファイル foo.h を考えます。

// File "foo.h"
template<typename T>
void foo();

ここで、ファイル foo.cpp が実際にそのテンプレート関数を定義しているとします。

// File "foo.cpp"
#include <iostream>
#include "foo.h"

template<typename T>
void foo()
{
  std::cout << "Here I am!\n";
}

ファイル main.cpp が foo() を呼び出してこのテンプレート関数を使用するとします。

// File "main.cpp"
#include "foo.h"

int main() {   foo<int>();   ... }

これら 2 つの .cpp ファイルをコンパイルしてリンクすると、ほとんどのコンパイラでリンカー エラーが生成されます。コンパイラがコードを生成するためには、テンプレート定義 (宣言だけでなく) と特定の型/テンプレートを「埋める」ために使用されるものの両方を確認する必要があるためです。テンプレート本体が .cpp で定義されている場合、コンパイラはそれを認識しないため、コードを生成しません。

修正方法は?

この問題には複数の解決策があります。テンプレート関数の定義を .h ファイルに移動することをお勧めします。

// File "foo.h"
template<typename T>
void foo()
{
  std::cout << "Here I am!\n";
}

ソースでは、通常どおり呼び出すことができます。

// File "main.cpp"
#include "foo.h"

int main() {   foo<int>();   ... }
于 2013-06-03T07:12:19.130 に答える