2012-03-05 61 views
1
#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结构设置COUT支持继承VirtualBase和命名,这两个的继承打印,我不能COUT使用DerivedB。在继承层次的多个层次上进行Printable支持的最佳方式是什么?另外,在派生类的print中调用Named :: print最简单的方法是什么?与继承

+0

什么是在你的结构声明中的'abstract'?这是无效的C++。 – 2012-03-05 23:21:48

+0

@DavidBrown:除非他把它当作宏。 – Linuxios 2012-03-05 23:24:14

+0

@Linux啊是的。如果是这样的话,您可能希望将它包含在您的代码示例中,并使其与宏的标准一致,以避免混淆user173342。 – 2012-03-05 23:29:51

回答

1

的问题是,因为DerivedBVirtualBase(这是一个Printable)和Named(这是一个Printable),所以operator<<试图DerivedB转换为Printable,但不能垂头丧气,因为它是两个Printable对象,并且它不知道要向哪个下拉。既然你只想要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++是一非常少的语言,可以做到这一点

+0

仍然给我C2594歧义错误与'结构命名的抽象:虚拟公共Printable',也试图把一个虚拟的DerivedB的命名继承,仍然没有去。 – user173342 2012-03-06 00:21:43

+0

好吧,如果我在VirtualBase上进行虚拟化并为继承Printable命名,它会编译(并且正常工作)!但它必须是两个,而不是像你的榜样。 – user173342 2012-03-06 00:23:10

+0

@ user173342:我认为它只有一个,但也许我的记忆力是关闭的。对于那个很抱歉! – 2012-03-06 00:24:47

0

你必须要符合条件,想用范围解析操作符(::)像这样调用哪个print

Named::print(cout); 
+0

谢谢,这解决了一个问题,但由于DerivedB的Printable继承模糊不清,它仍然无法编译。 – user173342 2012-03-05 23:32:23

+0

@ user173342它编译罚款给我。 [This](http://blogs.msdn.com/b/slippman/archive/2004/01/19/60166.aspx)似乎表明,但是C++/CLI不支持这样的多重继承。如果你的目标是C++/CLI,你应该把它添加到你的问题中。 – 2012-03-05 23:37:24

+0

我没有使用/ clr标记(设置为无公共语言运行时支持)......是否不会导致VC++ 2010不使用C++/CLI? – user173342 2012-03-05 23:47:36

0

好吧,我发现了一种通过模板化的运算符重载来解决它:

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

    return cout; 
} 

虽然我不确定这有多稳定。

+0

这是...不是一个好主意,不是所有 – 2012-03-06 00:13:00

+0

@MooingDuck出于好奇,它会做什么可怕的事情?你知道吗? – user173342 2012-03-06 00:17:26

+0

我发布了正确的回答你的问题,你的代码中的问题来自那些不会从'Printable'派生出来的类,它试图使用你的函数,并且可能会失败,也就是说,_every模板class_。 – 2012-03-06 00:20:23