operator<<
メンバー関数として定義すると、非メンバーを使用した場合とは異なる構文になりますoperator<<
。非メンバーoperator<<
は2項演算子であり、メンバーoperator<<
は単項演算子です。
// Declarations
struct MyObj;
std::ostream& operator<<(std::ostream& os, const MyObj& myObj);
struct MyObj
{
// This is a member unary-operator, hence one argument
MyObj& operator<<(std::ostream& os) { os << *this; return *this; }
int value = 8;
};
// This is a non-member binary-operator, 2 arguments
std::ostream& operator<<(std::ostream& os, const MyObj& myObj)
{
return os << myObj.value;
}
それで……本当にどうやってそれらを呼ぶのですか?演算子はいくつかの点で奇妙operator<<(...)
です。物事が意味をなすように頭の中に構文を書くように挑戦します。
MyObj mo;
// Calling the unary operator
mo << std::cout;
// which decomposes to...
mo.operator<<(std::cout);
または、非メンバーの2項演算子を呼び出そうとすることもできます。
MyObj mo;
// Calling the binary operator
std::cout << mo;
// which decomposes to...
operator<<(std::cout, mo);
これらの演算子をメンバー関数にしたときに、これらの演算子を直感的に動作させる義務はありません。必要に応じて、operator<<(int)
一部のメンバー変数を左シフトするように定義できます。コメントの数に関係なく、人々が少し油断している可能性があることを理解してください。書く。
最後に、オペレーター呼び出しの両方の分解が有効である場合があります。ここで問題が発生した場合は、その会話を延期します。
最後に、2項演算子のように見えるはずの単項メンバー演算子を記述するのがいかに奇妙であるかに注意してください。 )
struct MyObj
{
// Note that we now return the ostream
std::ostream& operator<<(std::ostream& os) { os << *this; return os; }
int value = 8;
};
この構文は、多くのコーダーを苛立たせます...
MyObj mo;
mo << std::cout << "Words words words";
// this decomposes to...
mo.operator<<(std::cout) << "Words words words";
// ... or even further ...
operator<<(mo.operator<<(std::cout), "Words words words");
cout
ここでチェーンの2番目の引数がどのようになっているかに注意してください。