如何正确地重载流操作符以在多态类中打印?

时间:2018-04-18 15:38:55

标签: c++ polymorphism operator-overloading

编辑:代码有错误,现在它编译但我仍然没有得到我想要的输出。

我试图重载Application.Runstd::cout等的流操作符,但我无法正确处理多态:我无法获得我想看到的输出。 我希望子类显示超类的内容,然后显示其内容,而超类只显示其内容。 这可以通过在std::fstream函数中引入新函数print_only_base()来实现,但我怀疑即使不添加新函数也可以使代码工作。

我想要的是什么

我有一个基类,当我这样做时,我希望在屏幕上显示一些属性

Base

有两个类Base base; std::cout << base; A继承自BBase是一个多态类,BaseA在流式传输时显示不同的输出。

我希望类B的对象仅显示其输出,而类Base的对象(A相同),如果将其视为B的实例,然后将其自身的输出视为Base(或A)。

在代码下面,我写了我期望的输出和我的(不工作)尝试。

B

主要功能:

#include <iostream>

class Base {
    virtual std::ostream & print(std::ostream stream) const {
        stream << "Base class output\n";
        return stream;
    }
public:
    friend std::ostream & operator<<(std::ostream & stream, const Base & obj) {
        return obj.print(stream);
    }
    virtual ~Base() {}
};

class A : public Base {
    std::ostream & print(std::ostream & stream) const {
        stream << "foo = " << foo << "\n";
        return stream;
    }
    int foo = 0;
public:
    friend std::ostream & operator<<(std::ostream & stream, const A & obj) {
        // here I would like to call the base class for printing, but I would enter in an infinite loop
        return obj.print(stream);
    }
    ~A() {}
};

class B : public Base {
    std::ostream & print(std::ostream & stream) const {
        stream << "bar = " << bar << "\n";
        return stream;
    }
    int bar = 0;
public:
    friend std::ostream & operator<<(std::ostream & stream, const B & obj) {
        // here I would like to call the base class for printing, but I would enter in an infinite loop
        return obj.print(stream);
    }
    ~B() {}
};

如何获得所需的行为?

1 个答案:

答案 0 :(得分:6)

解决方案非常简单。

  1. 仅为基类定义operator<<函数。没有必要为派生类型定义它。
  2. 依靠virtual函数机制来调用派生类的print函数。
  3. 在打印派生类特定内容之前,添加代码以从派生类调用Base::print。确保函数不是基类中的private
  4. #include <iostream>
    
    class Base {
       protected:
          virtual std::ostream & print(std::ostream& stream) const {
             stream << "Base class output\n";
             return stream;
          }
    
       public:
    
       // Define it only for the base class.
       friend std::ostream & operator<<(std::ostream & stream, const Base & obj) {
          return obj.print(stream);
       }
    
       virtual ~Base() {}
    };
    
    class A : public Base {
    
       std::ostream & print(std::ostream & stream) const {
          // Print the base class specific information first.
          Base::print(stream);
    
          // Print the derived class specific information.
          stream << "foo = " << foo << "\n";
          return stream;
       }
    
       int foo = 0;
       public:
       ~A() {}
    };
    
    class B : public Base {
    
       std::ostream & print(std::ostream & stream) const {
          // Print the base class-specific information first.
          Base::print(stream);
    
          // Print the derived class specific information.
          stream << "bar = " << bar << "\n";
          return stream;
       }
    
       int bar = 0;
       public:
       ~B() {}
    };
    

    通过这些更改,我得到了所需的输出。看到它在https://ideone.com/x6ti3W工作。