3

私は、前学期のクラスからいくつかの古いハードウェア課題を調べてきました。これは、リンクされたリスト オブジェクトを印刷するための特定の印刷機能でした。オーバーロードされたオペレーターが 2 つのパラメーターを取り、1 つが os オブジェクトである理由がわかりません。実際のリンク リスト オブジェクトを main.cpp に出力するときは、os オブジェクトを渡す必要はありませんでした。また、なぜosを返すのですか? "os <<" の代わりに cout を使用できないのはなぜですか?

ありがとうございました!

template <class T>
void List<T>::print(ostream & os) const
{
    os << "<";
    ListNode * curr = head;
    while (curr != NULL) {
        os << " " << curr->data;
        curr = curr->next;
    }
    os << " >";
}



// overloaded operator<<
template <class T>
ostream & operator<<(ostream & os, const List<T> & list)
{
    list.print(os);
    return os;
}
4

4 に答える 4

6

ところで、質問がされ、それがどれほど基本的なものであるかということで、私は非常に単純化した (かなり非公式であり、それほど衒学的ではありませんが) 回答をしようと思います。

オーバーロードされたオペレーターが 2 つのパラメーターを取り、1 つが os オブジェクトである理由がわかりません

operator<< は二項演算子です。左側と右側があります。あなたが書くとき:

cout << 123;

2 つのオペランド (引数) を使用してこの演算子を呼び出しています: 左側の 'cout' と右側の整数 '123'。

実際のリンク リスト オブジェクトを main.cpp に出力するときは、os オブジェクトを渡す必要はありませんでした。

印刷関数は、クラスのメンバー関数または演算子です。リストオブジェクトに対して使用する「this」ポインターが既にあるため、大雑把に言えば、最初の引数を明示的に渡す必要はないと暗黙的に推測します。左側のオペランドに対して既に動作する暗黙的に推定された「this」オブジェクトがないため、非メンバー演算子の場合はそうではありません。

次のようなコードを書くと:

my_list.print(cout);

これは、'my_list' と 'cout' という 2 つの引数を実際に渡すものと考えることができます。明示的に記述しなくても、「this」を介して「my_list」とそのメンバーにアクセスできます。次のように、print 関数を非メンバーとして記述した場合は、そうではありません。

template <class T>
void print(const List<T>& my_list, ostream& os);

これは、メンバー関数ではない演算子にも当てはまります。

また、なぜosを返すのですか?

ostream への参照を返すことで、次のようなステートメントを記述できます。

cout << "hello " << "world";

まず、operator<<(cout, "hello ") を呼び出します。これにより、別の ostream 参照が提供されます。これにより、operator<<(cout, "world") の呼び出しに進むことができます。たとえば、void が返された場合、左側のオペランドとして void を使用して「world」を出力しようとするため、1 つのステートメントでその演算子を 2 回呼び出すことはできません。

"os <<" の代わりに cout を使用できないのはなぜですか?

cout は基本的に ostream インターフェイスを実装しています。ofstream、ostringstream、およびその他のタイプの出力ストリームも同様です。特定の ostream の派生物ではなく、必要な基本的なインターフェイスの観点から記述することで、記述したコードを stdio ストリーム、ファイル ストリーム、ストリーム ストリームなどで動作させることができます。基本的に、それはあなたのコードを非常に一般的で再利用可能なものにします。ポリモーフィズムの概念に取り組むにつれて、この主題についてさらに学ぶことができます。

于 2012-02-27T20:00:43.053 に答える
2

グローバルな非メンバー関数であるためです。メンバー関数バージョンでは、最初のパラメーターは暗黙的に呼び出し元のオブジェクトですthis。つまり、クラスは常に左側にある必要があります。非メンバー関数では、明示的なパラメーターです。このようにして、任意の型を指定し、ソースを変更できないクラスの演算子をオーバーロードできます (少なくとも 1 つのパラメーターがユーザー定義型である場合)。

を使用する理由osostreamcout.

戻り値に対してより多くの呼び出しosを実行できるように戻ります。これにより、 と同じ のoperator<<ような演算子連鎖が可能になります。何かを返す場合は、 の戻り値では何もできないため、 で停止する必要があります。w << x << y << zoperator<<(operator<<(operator<<(w, x), y), z)voidw << xvoid

于 2012-02-27T19:46:59.167 に答える
0

実際のリンク リスト オブジェクトを main.cpp に出力するときは、os オブジェクトを渡す必要はありませんでした。

はい、そうでした.. のようなものです。cout << obj;ここで、cout はos出力ストリームです。

また、なぜosを返すのですか? "os <<" の代わりに cout を使用できないのはなぜですか?

これにより、連鎖が可能になります。cout << obj << " " << obj2;

"os <<" の代わりに cout を使用できないのはなぜですか?

これにより、出力ストリームが固定化されるため、ファイルやその他の出力に書き込むことができなくなります。

于 2012-02-27T19:50:57.247 に答える
0

オーバーロードされたオペレーターが 2 つのパラメーターを取り、1 つが os オブジェクトである理由がわかりません。実際のリンク リスト オブジェクトを main.cpp に出力するときは、os オブジェクトを渡す必要はありませんでした。

はい。cout << x_ cout_ x_operator<<

また、なぜosを返すのですか?

可能にするcout << x << yこと。これは として解析されます。つまり、 の戻り値に(cout << x) << y挿入されます。ycout << x

"os <<" の代わりに cout を使用できないのはなぜですか?

標準出力以外のストリームに出力したい場合があるからです。

于 2012-02-27T19:48:29.370 に答える