Оператор << и наследование - PullRequest
2 голосов
/ 04 марта 2011

У меня есть следующие классы в C ++:

class Event {
        //...
        friend ofstream& operator<<(ofstream& ofs, Event& e);

};


class SSHDFailureEvent: public Event {
    //...
    friend ofstream& operator<<(ofstream& ofs, SSHDFailureEvent& e);
};

Код, который я хочу выполнить:

main () {

 Event *e = new SSHDFailureEvent();
 ofstream ofs("file");
 ofs << *e; 

}

Это упрощение, но я хочу записать в файл несколько типов событий. в файле. Однако вместо использования оператора << SSHDFailureEvent он использует оператор << события. Есть ли способ избежать такого поведения? </p>

Спасибо

Ответы [ 4 ]

5 голосов
/ 04 марта 2011

Это не сработает, так как это вызовет operator<< для базового класса.

Вы можете определить виртуальную функцию print в базовом классе, переопределить ее для всего производного класса и определить operator<< только один раз,

class Event {

      virtual ofstream& print(ofstream & ofs) = 0 ; //pure virtual  

      friend ofstream& operator<<(ofstream& ofs, Event& e);
};

//define only once - no definition for derived classes!
ofstream& operator<<(ofstream& ofs, Event& e)
{
   return e.print(ofs); //call the virtual function whose job is printing!
}
4 голосов
/ 04 марта 2011

Попробуйте:

class Event
{
        //...
        friend ofstream& operator<<(ofstream& ofs, Event& e)
        {
            e.print(ofs);
            return ofs;
        }

        virtual void print(std::ofstream& ofs)
        {
             ofs << "Event\n";
        }

};


class SSHDFailureEvent: public Event
{
        virtual void print(std::ofstream& ofs)
        {
             ofs << "SSHDFailureEvent\n";
        }
};
1 голос
/ 04 марта 2011

Ответы до сих пор имеют правильную идею, но прежде чем вы запустите и реализуете его, сделайте два изменения:

  • Использовать ostream, а не ofstream
  • Функция печати должна быть постоянной.

Таким образом:

class Event
{
public:
    virtual ~Event();
    virtual std::ostream& printTo( std::ostream& ) const /*= 0*/;
   // other public methods
};

/*inline*/ std::ostream& operator<<(std::ostream& os, const Event& event)
{
    return event.printTo(os); 
}

Пока print (или printTo) общедоступны, нет необходимости заставлять оператора потока перегружать друга.

У вас есть возможность иметь реализацию по умолчанию или сделать метод печати чисто виртуальным.

Вы также можете сделать print() общедоступной не виртуальной функцией, которая вызывает защищенную или приватную виртуальную функцию, как в случае со всеми виртуальными функциями.

0 голосов
/ 04 марта 2011

Я вижу две возможности здесь:

Вызвать явный метод печати для класса, который вы пытаетесь распечатать. Например внедрить

vritual print(std::ofstream& os);

в базе и дети.

  • Или -

Попытка динамически привести базовый класс к его дочерним элементам.

SSHDFailureEvent* fe = dynamic_cast<SSHDFailureEvent*>(new Event());
...