メンバー関数としてオーバーロードされた場合、a << b
はa.operator<<(b)
と解釈されるため、1つの明示的なパラメータ(隠しパラメータとしてthis
)のみが使用されます。
これは、オーバーロードが左側のオペランドとして使用されるクラスの一部であることを必要とするため、普通のostream
などでは役に立ちません。オーバーロードはクラスの一部ではなく、ostream
クラスの一部である必要があります。 ostream
を変更することは許可されていないので、そのことはできません。それは代替としてグローバルオーバーロードだけを残します。
があり、しかし、あなたはグローバル演算子をオーバーロードが、それはメンバ関数を呼び出す必要があり、かなり広く使用されているパターン:
class whatever {
// make this public, or the global overload a friend.
std::ostream &write(std::ostream &dest) const {
// write self to dest
}
};
std::ostream &operator<<(std::ostream &os, whatever const &w) {
return w.write(os);
}
あなたはポリモーフィック行動をしたい場合はとき/これは特に便利です。オーバーロードされた演算子を多形体にすることはできませんが、それはvirtual
というメンバ関数を作成するので、とにかに多態的に動作します。
編集:(私が望む)状況を明確にするには、これをいくつかの方法で行うことができます。最初の、おそらく最も明白なのは、私たちのwrite
メンバーをパブリックにし、グローバルオペレータにそれを呼び出させることです。それが公開されているので、我々は、オペレータがそれを使用できるように特別な何かをする必要はありません。
:
class myClass {
public:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
// since `write` is public, we can call it without any problem.
return m.write(os);
}
第二の代替はwrite
をプライベートに、それにアクセスを与えるためにoperator<<
友人を宣言することです
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access:
friend std::ostream &operator<<(std::ostream &, myClass const &);
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
ほぼ第二のようなものだ第三の可能性があります:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access.
// We also implement it right here inside the class definition though:
friend std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
};
この第三の場合は、C +にかなり奇妙(及び少し知られている)ルールを使用して+ "名前インジェクション"と呼ばれる。コンパイラはfriend
関数をクラスの一部にすることはできないことを知っているので、メンバ関数を定義する代わりに、その関数の名前を周囲のスコープ(この場合はグローバルスコープ)に "注入"します。クラス定義内にoperator<<
が定義されていても、それはではありません。メンバー関数はまったくありません。これはグローバル関数です。
'operator <<'がクラス内でpublicとして宣言されていて、クラス内で 'MyClass :: operator <<'として実装されていない場合はどうなりますか? 「友人」は必要ですか? –
興味深い。クラス内で宣言され、非メンバ関数として実装され、そのクラスのpublicメンバ関数を呼び出すクラスの友人ではありません。 –
@ 0A0D:私は私がついてるかどうかはわかりません。私の前のコメントでは、 "it"はメンバ関数を参照していました。あなたは何か他のことについて話していますか? –