在具有多层继承的结构中设置cout支持

时间:2012-03-05 23:15:16

标签: c++ cout

#include <iostream>
#include <string>

struct Printable abstract
{
 friend std::ostream& operator<<(std::ostream& cout, const Printable& obj)
 {
  obj.print(cout);

  return cout;
 }

 virtual void print(std::ostream& cout) const = 0;
};

struct VirtualBase abstract : public Printable
{
 //stuff
};

struct Named abstract : public Printable
{
 std::string name;

 void print(std::ostream& cout) const
 {
  cout << "Name: " << name;
 }
};

struct DerivedA : public VirtualBase
{
 void print(std::ostream& cout) const
 {
  cout << "DerivedA";
 }
};

struct DerivedB : public VirtualBase, public Named
{
 void print(std::ostream& cout) const
 {
  cout << "DerivedB";

  dynamic_cast<const Named*>(this)->print(cout);
  //Is there a better way to call Named::print?
 }
};

由于DerivedB继承了VirtualBase和Named,并且这两个都继承了Printable,我不能将DerivedB与cout一起使用。在继承层次结构的多个层上获得Printable支持的最佳方法是什么?另外,在派生类的print中调用Named :: print的最简单方法是什么?

3 个答案:

答案 0 :(得分:1)

问题是因为DerivedBVirtualBasePrintable}和NamedPrintable),所以operator<<尝试将DerivedB转换为Printable,但无法向下转换,因为它是两个 Printable个对象,并且它不会知道要转向哪个。由于您只希望从{em>一个 DerivedB对象派生Printable,因此您必须使用虚拟继承

   normal inheritance:            virtual inheritance:
Printable      Printable                 Printable
   |               |                    /        \
VirtualBase      Named          VirtualBase      Named
       \         /                     \         /
        DerivedB                         DerivedB

简单地完成了:

struct Named abstract : virtual public Printable
struct VirtualBase abstract : virtual public Printable

请注意,具有虚拟继承的类比没有虚拟继承的类要大,并且略微慢,但另一方面,C ++是可以在以下情况下执行此操作的极少数语言之一所有

答案 1 :(得分:0)

您只需要使用范围解析运算符(print)来限定要调用的::,如下所示:

Named::print(cout);

答案 2 :(得分:0)

好的,我找到了一种通过模板化运算符重载来修复它的方法:

 template<typename P> friend std::ostream& operator<<(std::ostream& cout, const P& obj)
 {
  obj.print(cout);

  return cout;
 }
但是,我不确定这是多么稳定。