web-dev-qa-db-ja.com

cout <<は実際にどのように機能しますか?

std::cout<<をどのように使用できるのか疑問に思いました。

私の主な問題は、何かのインスタンスとしてのstd::coutかどうかです。基本的に、<<はどのように定義されていますか?カスタムクラスでこれを行う場合、ある種のインスタンスが必要です...

私はそれをvoidポインタまたは何かを使った一種のハックとして実装することを見ることができましたが、それが実際に行われる方法を見たいと思います。

ここの誰か知っていますか?ありがとう

47
Ori

std::coutstd::ostreamのインスタンスです。 std::cout << "something"は、operator<<のインスタンスに対して行われるように、std::ostreamオーバーロードの1つを呼び出します。

コンソールを参照するという点で「特別」ですが、それ以外はofstreamまたはostringstreamとまったく同じように動作します。

[〜#〜] edit [〜#〜]:チェーンは他の演算子と同じように機能します。考慮してください:

class MyType
{
    friend std::ostream& operator<<(std::ostream& target, const MyType& source);
    int val;
public:
    MyType()
        : val(0)
    { }
    MyType& Add(int toAdd)
    {
        val += toAdd;
        return *this;
    }
};

MyType& operator+(MyType& target, int toAdd)
{
    return target.Add(toAdd);
}

std::ostream& operator<<(std::ostream& target, const MyType& source)
{
    target << source.val;
    return target; //Make chaining work
}

int main()
{
    MyType value1;
    value1 + 2 + 3 + 4;
    std::cout << value1 << " and done!" << std::endl;
}

この場合、MyTypeでの+ sの連鎖は、<<std::ostreamの上で機能するのと同じ理由で機能します。 +<<はどちらも左結合です。つまり、左から右に評価されます。オーバーロードされた演算子の場合、演算子は同等の関数呼び出しに置き換えられます。

EDIT2:もう少し詳しく:

あなたがコンパイラで、解析しているとしましょう

std::cout << value1 << " and done!" << std::endl;

まず、<<は関連付けられたままなので、左側から始めます。最初の<<を評価し、それを関数呼び出しに変換します。

operator<<(std::cout, value1) << " and done!" << std::endl;

次に、もう一度std::ostreamoperator<<の呼び出しの結果)とchar *があり、これをもう一度関数呼び出しに変換します。

operator<<(operator<<(std::cout, value1)," and done!") << std::endl;

以下同様に、ステートメント全体を処理します。

47
Billy ONeal