#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的最简单方法是什么?
答案 0 :(得分:1)
问题是因为DerivedB
是VirtualBase
(Printable
}和Named
(Printable
),所以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;
}
但是,我不确定这是多么稳定。