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

Nis*_*sba 2 c++ polymorphism operator-overloading

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

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

我想得到什么

我有一个基类,它具有一些我希望在屏幕上显示的属性

Base base;
std::cout << base;
Run Code Online (Sandbox Code Playgroud)

有两类,AB从它继承Base.Base是一个多态类,AB在流式传输时显示不同的输出.

我希望类的对象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() {}
};
Run Code Online (Sandbox Code Playgroud)

主功能:

int main(int argc, char * argv[]) {
    Base * base = new Base();
    A * a = new A();
    B * b = new B();
    Base * a_inside = dynamic_cast<Base *>(a);

    std::cout << *base << "\n";
    std::cout << *a << "\n";
    std::cout << *b << "\n";
    std::cout << *a_inside << "\n";

    delete base;
    delete a;
    delete b;

    /* output I want to get
       Base class output

       Base class output
       foo = 0

       Base class output
       bar = 0

       Base class output
       foo = 0
    */


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能获得理想的行为?

R S*_*ahu 6

解决方案非常简单.

  1. operator<<仅为基类定义函数.无需为派生类型定义它.
  2. 依靠virtual函数机制来调用print派生类的功能.
  3. Base::print在打印派生类特定内容之前,添加要从派生类调用的代码.确保该函数不在private基类中.

#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() {}
};
Run Code Online (Sandbox Code Playgroud)

通过这些更改,我得到了所需的输出.请参阅https://ideone.com/x6ti3W.