10

ostream::operator <<C++リファレンスを見た後、

次の宣言に気付きました。

ostream& operator<< (bool val);
ostream& operator<< (short val);
ostream& operator<< (unsigned short val);
ostream& operator<< (int val);
ostream& operator<< (unsigned int val);
ostream& operator<< (long val);
ostream& operator<< (unsigned long val);
ostream& operator<< (float val);
ostream& operator<< (double val);
ostream& operator<< (long double val);
ostream& operator<< (void* val);
ostream& operator<< (streambuf* sb );
ostream& operator<< (ostream& (*pf)(ostream&));
ostream& operator<< (ios& (*pf)(ios&));
ostream& operator<< (ios_base& (*pf)(ios_base&));

しかし、その後、次の宣言もあることがわかりました。

ostream& operator<< (ostream& os, char c);
ostream& operator<< (ostream& os, signed char c);
ostream& operator<< (ostream& os, unsigned char c);
ostream& operator<< (ostream& os, const char* s);
ostream& operator<< (ostream& os, const signed char* s);
ostream& operator<< (ostream& os, const unsigned char* s);

文字/文字列出力演算子がメンバー関数ではないのはなぜですか?

4

5 に答える 5

6

オペレーターの最初のグループは、ストリーム クラスのメンバーです。

2 番目のグループのような、ほとんどの演算子のオーバーロードはそうではありません。


理由については、おそらく歴史的な事故です。組み込み型の演算子はストリーム クラスに追加できますが、明らかに (C++ が標準化されるずっと前から) 追加されていました。標準は、ここで既存の慣行を文書化するだけです。

ユーザー定義型の演算子は明らかにストリーム クラスに追加できないため、フリー関数として実装されます。

振り返ってみると、すべての演算子を関数から解放する方がより一貫性がありましたが、そうすると一部の古いプログラムが壊れる可能性があります。

于 2013-04-15T12:29:11.580 に答える
2

他の人は違いを説明していますが、ここにそれらが分割されている理由についての私のショットがあります。

パラメータとしてバリアントを取る非メンバー バージョンcharは、ターゲット ストリームの基本文字型の型に応じて特殊化され、ロケールに応じて処理されますo << '1'。)。oo << 33obasic_ostream<wchar_t>

たとえば、書き込み先は拡張されますが、書き込み先は拡張されません ( char27.6.2.5.4 )。したがって、実際には の複数のオーバーロードがあります。たとえば、次のようになります。basic_ostream<wchar_t>basic_ostream<char>operator<<

basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr, char _Ch)
basic_ostream<char, _Traits>& <<(basic_ostream<char, _Traits>& _Ostr, char _Ch)

それらがメンバー関数として定義されている場合、標準ではメンバー関数の部分的な特殊化が許可されていないため、単一のメンバーだけでなく、クラス全体を部分的に特殊化する必要があるため、そのように特殊化することはできません。

于 2013-04-15T12:57:28.060 に答える
0

operator<< が char is not a member function を取る理由は、文字をストリームに書き込む ostream で定義された関数が既に存在するためです。

basic_ostream& put(Ch c);
basic_ostream& write(const Ch* p, streamsize n);

したがって、これらの演算子は、これら 2 つの関数を内部的に使用する非メンバー関数になります。

于 2014-11-23T09:27:56.563 に答える
-1

最初のシリーズはメンバー関数であるreturn *thisため、演算子チェーンが機能します。

2番目のシリーズは独立した関数です(あなたが言うように、任意のクラスに追加できるので、それらをにストリーミングできますstd::ostream)、this返す必要がなく、return os代わりに演算子チェーンを機能させます。

どちらも呼び出しサイトで同じように機能することに注意してください。

于 2013-04-15T12:29:12.523 に答える