我有一個抽象基類,它充當接口。來自兩個派生類的多繼承
我有兩套派生類,它們實現了抽象類的一半。 (一個「set」定義了與初始化有關的抽象虛擬方法,另一個「set」定義了與實際「work」相關的那些)。然後我有派生類,它們使用多重繼承來構造完全定義的類本身不添加任何東西)。
所以:(壞的僞代碼)
class AbsBase {
virtual void init() = 0;
virtual void work() = 0;
}
class AbsInit : public AbsBase {
void init() { do_this(); }
// work() still abs
}
class AbsWork : public AbsBase {
void work() { do_this(); }
// init() still abs
}
class NotAbsTotal : public AbsInit, public AbsWork {
// Nothing, both should be defined
}
首先,我能做到這一點?我可以從兩個派生自同一個Base的類繼承嗎? (但願如此)。
這是「真正的問題」,雖然(我撒謊了一點,以簡化示例)。
我真的走了,要做的就是非抽象訪問方法添加到基類:
class AbsBase {
public:
void init() { init_impl(); }
void work() { work_impl(); }
private:
virtual void init_impl() = 0;
virtual void work_impl() = 0;
}
因爲,一個常見的成語就是讓所有的虛擬方法專用。不幸的是,現在AbsInit和AbsWork都繼承了這些方法,所以NotAbsTotal繼承了「每個都有兩個」(我意識到我可能在編譯時會屠殺實際發生的事情)。
無論如何,g ++會在嘗試使用該類時抱怨:「對成員init()的請求不明確」。
我假設,如果我使用我的AbsBase類作爲純接口,可以避免這種情況(假設頂部示例有效)。
所以: - 我的方式與我的實施? - 這是虛擬方法私人化的一個限制嗎? - 我如何重構我的代碼來做我想做的事? (提供一個通用的接口,但允許的方式換出實現爲成員函數「套」)
編輯:
看來我不是第一個: http://en.wikipedia.org/wiki/Diamond_problem
似乎虛擬繼承是這裏的解決方案。我以前聽說過虛擬繼承,但是我沒有把頭繞在它周圍。我仍然樂於接受建議。
這個結果不錯,即使我非虛公共方法。但是,我將不得不嘗試看看在將基類型指針用於派生類型的對象時會發生什麼情況,以確保虛擬繼承像虛函數重載一樣工作:) – mmocny 2008-10-31 20:21:38
當從虛擬基類轉換爲派生類時,總是需要使用dynamic_cast <>,這又要求在虛擬基礎中定義虛擬方法。虛擬基地的簡單使用應該沒有問題 - 它將以多態方式授予對派生類的訪問權限。 – 2008-10-31 23:29:10