2012-03-05 105 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