web-dev-qa-db-ja.com

演算子<<を仮想化していますか?

仮想<<演算子を使用する必要があります。しかし、私が書こうとすると:

virtual friend ostream & operator<<(ostream& os,const Advertising& add);

コンパイラエラーが発生する

エラー1エラーC2575: '演算子<<':仮想化できるのはメンバー関数とベースのみ

このオペレーターを仮想化するにはどうすればよいですか?

41
inna karpasas

この設定の問題は、上記で定義したoperator <<がフリー関数であり、仮想にすることができない(レシーバーオブジェクトがない)ことです。関数を仮想化するには、あるクラスのメンバーとして定義する必要があります。これは、operator <<をクラスのメンバーとして定義すると、オペランドの順序が正しくなくなるため、ここで問題になります。

class MyClass {
public:
    virtual ostream& operator<< (ostream& out) const;
};

という意味です

MyClass myObject;
cout << myObject;

コンパイルされませんが、

MyClass myObject;
myObject << cout;

合法になります。

これを修正するには、ソフトウェアエンジニアリングの基本定理を適用できます。間接参照の別の層を追加することで、問題を解決できます。 operator <<を仮想化するのではなく、次のようなクラスに新しい仮想関数を追加することを検討してください。

class MyClass {
public:
    virtual void print(ostream& where) const;
};

次に、operator <<を次のように定義します。

ostream& operator<< (ostream& out, const MyClass& mc) {
    mc.print(out);
    return out;
}

このようにして、operator << free関数は正しいパラメーター順序を持っていますが、operator <<の動作はサブクラスでカスタマイズできます。

お役に立てれば!

78
templatetypedef

演算子<<を定義して、仮想印刷メソッドを呼び出します。

class Base
{
    protected:
        virtual void print(std::ostream& str) const = 0;
    public:
        friend std::ostream& operator<<(std::ostream& str, Base const& data)
        {
            data.print(str);
            return str;
        }
}
34
Martin York

クラスの階層に出力機能を本当に提供したいようですが、その場合はfriend operator <<virtual関数を呼び出します。

class Parent
{
public:
    friend std::ostream& operator<< (std::ostream& os, const Parent& p);
    // ... other class stuff
protected:
    virtual void printMyself(std::ostream& os) const
    {
        // do something if you must, or make this a pure virtual
    }
};

std::ostream& operator<< (std::ostream& os, const Parent& p)
{
    p.printMyself(os);
    return os;
}

class Child : public Parent
{
    // other class stuff...
protected:
    virtual void printMyself(std::ostream os) const
    {
        // whatever you need to do
    }
};

C++ FAQ でも詳しく説明されています

2
wkl