Делаем оператора << виртуальным? - PullRequest
40 голосов
/ 31 декабря 2010

Мне нужно использовать виртуальный оператор <<. Однако когда я пытаюсь написать: </p>

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

Я получаю ошибку компилятора

Ошибка 1, ошибка C2575: «оператор <<»: могут быть только функции-члены и базы виртуальный </p>

Как включить виртуальный оператор?

Ответы [ 3 ]

73 голосов
/ 31 декабря 2010

Проблема с этой настройкой заключается в том, что оператор <<, который вы определили выше, является бесплатной функцией, которая не может быть виртуальной (у нее нет объекта-получателя).Чтобы сделать функцию виртуальной, она должна быть определена как член некоторого класса, что здесь проблематично, потому что если вы определите operator << как член класса, то операнды будут в неправильном порядке: </p>

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

означает, что

MyClass myObject;
cout << myObject;

не будет компилироваться, но

MyClass myObject;
myObject << cout;

будет допустимым.

Чтобы исправить это, вы можете применить Основную теоремупрограммного обеспечения - любая проблема может быть решена путем добавления еще одного слоя косвенности.Вместо того чтобы делать оператор << виртуальным, рассмотрите возможность добавления в класс новой виртуальной функции, которая выглядит следующим образом: </p>

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

Затем определите оператор << как </p>

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

Таким образом,у оператора << свободная функция имеет правильный порядок параметров, но поведение оператора << можно настроить в подклассах. </p>

Надеюсь, это поможет!

31 голосов
/ 31 декабря 2010

Вы определяете своего оператора << для вызова метода виртуальной печати: </p>

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;
        }
}
2 голосов
/ 31 декабря 2010

Похоже, вы действительно хотите предоставить функции вывода для иерархии классов, и если это так, вы можете предоставить 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

...