1

爲什麼這個工程虛方法與多重繼承

struct Base { 
    virtual void visit(const A &) { }; 
    virtual void visit(const B &) { }; 
} 

不同的表現,這抱怨歧義調用訪問方法時

template< typename T > 
struct X { 
    virtual void visit(const T &) { }; 
}; 

struct Base: X<A>, X<B> { }; 

這也說明了同樣的問題:

struct Y { 
    virtual void visit(const A &) { }; 
}; 

struct Z { 
    virtual void visit(const B &) { }; 
}; 

struct Base: Z, Y { }; 

不知何故,它看起來像虛擬函數簽名的多重繼承混亂...

用gcc版本4.8.0 20130411(預發佈)

+0

[multiple-inheritance-template-class]可能的重複(http://stackoverflow.com/questions/3360892/multiple-inheritance-template-class) – yngccc 2013-05-09 01:02:49

+0

備註:你不需要';'在' }'在'virtual void visit(const A &) { };'''結束函數體,這很難看。 – curiousguy 2013-05-14 05:07:40

回答

0

這裏虛擬岬是無關緊要的,事實上2基類是模板類是無關緊要的。用同樣的問題一個簡單的代碼是:

struct A { 
    void f(const A &) { } 
}; 

struct B { 
    void f(const B &) { } 
}; 

struct Der: A,B { }; 

這裏Der有兩個繼承成員:A::f(const A &)B::f(const B &);他們可以通過這種方式調用:

Der d; 
d.A::f(d); 
d.B::f(d); 

這樣:

d.f((A&)d); // error: ambiguous name lookup 
d.f((B&)d); // error: ambiguous name lookup 

成員函數重載決議並的工作,你的思維方式(發現無論f然後保持其中一個有一個兼容的參數列表)。

在C++中,成員名稱查找發現所有非隱藏成員聲明與給定的名稱,所以在這裏找到A::f(const A &)B::f(const B &),那麼如果這些成員不在同一類中聲明立即失敗。

您可以通過在同一個類中添加兩個聲明解決了這個問題:

struct Der: A,B { 
    using A::f; // imports A::f(const A &) 
    using B::f; // imports B::f(const B &) 
}; 

然後,你可以這樣做:

Der d; 
d.f((A&)d); // OK: Der::f(&A) 

記住:這純粹是一個成員的名字,查找歧義。