2012-05-24 16 views
64

ああオペレータは<<取る必要があり、正確に一つの引数

#include "logic.h" 
... 

class A 
{ 
friend ostream& operator<<(ostream&, A&); 
... 
}; 

logic.cpp

#include "a.h" 
... 
ostream& logic::operator<<(ostream& os, A& a) 
{ 
... 
} 
... 

私は、コンパイル、それは言う:

のstd :: ostreamに&ロジック::オペレータ< <(std :: ostream &、A &) 'は、引数。

何が問題ですか?

答えて

90

問題は、あなたが

a)は2番目の引数は(this)と

b)は、それはあなたがそれを行うやりたいことではないだろう、すなわち拡張暗黙的であることを意味する、クラス内でそれを定義することですstd::ostream

あなたがフリー機能として定義する必要があります。

class A { /* ... */ }; 
std::ostream& operator<<(std::ostream&, const A& a); 
+7

さらに、彼はfriend関数として宣言し、私のようにmber機能。 – asaelr

40

フレンド関数はメンバ関数ではないので、問題は、あなたがAの友人としてoperator<<を宣言することである:

friend ostream& operator<<(ostream&, A&); 

それをクラスのメンバ関数として定義しようとするlogic

ostream& logic::operator<<(ostream& os, A& a) 
      ^^^^^^^ 

logicがクラスであるのか名前空間であるのか混同していますか?

2つの引数を取るメンバーoperator<<を定義しようとしたためです。つまり、暗黙のthisパラメータを含む3つの引数が必要です。演算子は2つの引数しか取ることができないので、a << bを書くときは、2つの引数はabです。

あなたはそれがそのクラスとは何の関係もありませんので、間違いないlogicの一員として、 -member機能としてostream& operator<<(ostream&, const A&)を定義したいです!

std::ostream& operator<<(std::ostream& os, const A& a) 
{ 
    return os << a.number; 
} 
0

この問題はテンプレート化されたクラスで発生しました。ここ は、私が使用していたより一般的なソリューションです:

template class <T> 
class myClass 
{ 
    int myField; 

    // Helper function accessing my fields 
    void toString(std::ostream&) const; 

    // Friend means operator<< can use private variables 
    // It needs to be declared as a template, but T is taken 
    template <class U> 
    friend std::ostream& operator<<(std::ostream&, const myClass<U> &); 
} 

// Operator is a non-member and global, so it's not myClass<U>::operator<<() 
// Because of how C++ implements templates the function must be 
// fully declared in the header for the linker to resolve it :(
template <class U> 
std::ostream& operator<<(std::ostream& os, const myClass<U> & obj) 
{ 
    obj.toString(os); 
    return os; 
} 

今:CPPに隠れされようとしている場合 *私のtoString()関数はinlineにできません。 *ヘッダーにコードが付いているので、取り除くことができませんでした。 *演算子はtoString()メソッドを呼び出しますが、インライン化されていません。

オペレータの本文< <は、フレンド節またはクラス外で宣言できます。どちらのオプションも醜いです。

たぶん私は誤解や不足している何かを、ちょうどオペレータテンプレートは、GCCにリンクしません、前方宣言しています:(

これはあまりにも動作します。

template class <T> 
class myClass 
{ 
    int myField; 

    // Helper function accessing my fields 
    void toString(std::ostream&) const; 

    // For some reason this requires using T, and not U as above 
    friend std::ostream& operator<<(std::ostream&, const myClass<T> &) 
    { 
     obj.toString(os); 
     return os; 
    } 
} 

私はあなたにもできると思います< <を実装するためにテンプレート化されていない親クラスを使用し、virtual toString()メソッドを使用する場合は、ヘッダーの宣言を強制的にテンプレート化する問題を避けてください。

関連する問題