できれば非会員・非フレンド機能として。
Herb Sutter と Scott Meyers によって説明されているように、カプセル化を促進するために、メンバー関数よりも非フレンド非メンバー関数を優先します。
C++ ストリームのように、選択の余地がなく、非メンバー関数を使用する必要がある場合もあります。
ただし、これらの関数をクラスのフレンドにする必要があるという意味ではありません。これらの関数は、クラス アクセサーを介してクラスにアクセスできます。これらの関数をこのように書くことに成功した場合、あなたは勝ちました。
演算子 << および >> プロトタイプについて
あなたの質問で挙げた例は間違っていると思います。例えば;
ostream & operator<<(ostream &os) {
return os << paragraph;
}
このメソッドがストリームでどのように機能するかを考え始めることさえできません。
<< および >> 演算子を実装する 2 つの方法を次に示します。
タイプ T のストリームのようなオブジェクトを使いたいとしましょう。
そして、タイプ Paragraph のオブジェクトの関連データを T から抽出/T に挿入したいとします。
ジェネリック演算子 << および >> 関数プロトタイプ
最初は関数としてです:
// T << Paragraph
T & operator << (T & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// T >> Paragraph
T & operator >> (T & p_oInputStream, const Paragraph & p_oParagraph)
{
// do the extraction of p_oParagraph
return p_oInputStream ;
}
汎用演算子 << および >> メソッドのプロトタイプ
2番目はメソッドとしてです:
// T << Paragraph
T & T::operator << (const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return *this ;
}
// T >> Paragraph
T & T::operator >> (const Paragraph & p_oParagraph)
{
// do the extraction of p_oParagraph
return *this ;
}
この表記法を使用するには、T のクラス宣言を拡張する必要があることに注意してください。STL オブジェクトの場合、これは不可能です (それらを変更することは想定されていません...)。
T が C++ ストリームの場合はどうなるでしょうか。
以下は、C++ ストリームの同じ << および >> 演算子のプロトタイプです。
汎用の basic_istream および basic_ostream の場合
ストリームの場合は C++ ストリームを変更できないため、関数を実装する必要があることに注意してください。つまり、次のような意味です。
// OUTPUT << Paragraph
template <typename charT, typename traits>
std::basic_ostream<charT,traits> & operator << (std::basic_ostream<charT,traits> & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// INPUT >> Paragraph
template <typename charT, typename traits>
std::basic_istream<charT,traits> & operator >> (std::basic_istream<charT,traits> & p_oInputStream, const CMyObject & p_oParagraph)
{
// do the extract of p_oParagraph
return p_oInputStream ;
}
char istream および ostream の場合
次のコードは、文字ベースのストリームに対してのみ機能します。
// OUTPUT << A
std::ostream & operator << (std::ostream & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// INPUT >> A
std::istream & operator >> (std::istream & p_oInputStream, const Paragraph & p_oParagraph)
{
// do the extract of p_oParagraph
return p_oInputStream ;
}
Rhys Ulerich は、char ベースのコードはその上の汎用コードの「特殊化」にすぎないという事実についてコメントしました。もちろん、Rhys の言うとおりです。文字ベースの例の使用はお勧めしません。読みやすいので、ここでのみ示します。char ベースのストリームでのみ作業する場合にのみ実行可能であるため、wchar_t コードが一般的なプラットフォーム (つまり、Windows) では避ける必要があります。
これが役立つことを願っています。