ああ
#include "logic.h"
...
class A
{
friend ostream& operator<<(ostream&, A&);
...
};
logic.cpp
#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...
私がコンパイルすると、それは言います:
std :: ostream&logic :: operator <<(std :: ostream&、A&) 'は引数を1つだけとる必要があります。
何が問題ですか?
問題は、クラス内で定義することです。
a)2番目の引数が暗黙的(this
)であり、
b)望んでいること、つまりstd::ostream
を拡張しません。
自由関数として定義する必要があります:
class A { /* ... */ };
std::ostream& operator<<(std::ostream&, const A& a);
フレンド関数はメンバー関数ではないため、問題はoperator<<
をA
のフレンドとして宣言することです。
friend ostream& operator<<(ostream&, A&);
それをクラスlogic
のメンバー関数として定義してみてください
ostream& logic::operator<<(ostream& os, A& a)
^^^^^^^
logic
がクラスなのか名前空間なのか混乱していますか?
エラーは、2つの引数をとるメンバーoperator<<
を定義しようとしたためです。つまり、暗黙のthis
パラメーターを含む3つの引数が必要です。演算子は2つの引数のみを取ることができるため、a << b
を記述すると、2つの引数はa
とb
になります。
ostream& operator<<(ostream&, const A&)
をnon-member関数として定義します。logic
のメンバーとしてではなく、そのクラスとは関係がないためです!
std::ostream& operator<<(std::ostream& os, const A& a)
{
return os << a.number;
}
テンプレート化されたクラスでこの問題に遭遇しました。私が使用しなければならなかったより一般的なソリューションは次のとおりです。
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;
}
現在:*私のtoString()関数は、cppに隠れようとする場合、インラインにできません。 *ヘッダーにいくつかのコードが残っています。それを取り除くことができませんでした。 *オペレーターはtoString()メソッドを呼び出しますが、インライン化されていません。
Operator <<の本体は、friend節またはクラス外で宣言できます。両方のオプションはいです。 :(
多分私は何かを誤解したり見落としたりしているかもしれませんが、演算子テンプレートを前方宣言するだけでは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;
}
}
Operator <<を実装するためにテンプレート化されていない親クラスを使用し、仮想toString()メソッドを使用する場合、ヘッダーの宣言を強制するテンプレートの問題も回避できると思います。