c++ - 如何正确重载流运算符以在多态类中进行打印?

标签 c++ polymorphism operator-overloading

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

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

我想得到什么

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

Base base;
std::cout << base;

有两个类,AB 继承自 BaseBase 是一个多态类,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() {}
};

主要功能:

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;
}

如何获得所需的行为?

最佳答案

解决方案非常简单。

  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() {}
};

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

关于c++ - 如何正确重载流运算符以在多态类中进行打印?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49903769/

相关文章:

c# - 覆盖对象的虚拟方法

java - 如何像使用接口(interface)一样使用枚举?

c++ - 为什么 'Base Class object' 不能调用它自己的虚函数? C++

c++ - 快捷方式触发时的 Lambda 表达式 (Qt)

c++ - 对象指针 vector ,一般帮助和混淆

c++ - 根据 C++ 中的列对 csv 文件进行排序

java - 跨不同类加载器覆盖默认访问器方法会破坏多态性

c++ - 未调用 operator delete() 的类实现

C++ 模板<运算符>

c++ - C++ 中的运算符 <<, "no operator found which takes right hand-operator"和 "already has a body"错误