メンバー関数として定義するoperator<<
と、非メンバーを使用した場合とは異なる分解構文になりますoperator<<
。非メンバーoperator<<
は二項演算子であり、メンバー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);
または、非メンバーの二項演算子を呼び出そうとすることもできます。
MyObj mo;
// Calling the binary operator
std::cout << mo;
// which decomposes to...
operator<<(std::cout, mo);
これらの演算子をメンバー関数にするときに直感的に動作させる義務はありません。必要に応じて、operator<<(int)
メンバー変数を左シフトするように定義できます。コメントの数に関係なく、人々が少し不意を突かれる可能性があることを理解してください。書きます。
最後に、オペレーター呼び出しの両方の分解が有効な場合があります。ここで問題が発生する可能性があり、その会話を延期します。
最後に、二項演算子のように見えるはずの単項演算子を書くのがいかに奇妙であるかに注意してください(メンバー演算子を仮想にすることができるので.....また、このパスを展開して実行しないようにしようとしています...。 )。
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番目の引数がどのようになっているのかに注意してください....奇妙な権利ですか?