2016-05-29 32 views
19
鑑於

這種情況下允許:如何禁止C++派生類從基地獲得,而是從另一個派生類

class GrandParent {}; 
class Parent : public GrandParent {}; 
class Child : public Parent {}; /// Ok 
class Child : public GrandParent {}; /// Is it possible to force a compilation error? 
+4

如果它的唯一目的是作爲'Parent'一個基類,: 你應該子類聲明後添加以下代碼爲什麼'GrandParent'存在? –

+1

@PeteBecker對於「普通」繼承可能沒有理由,但對於技巧,當然(基於成員的成語,EBO,主要類的普通成員及其專業化......此列表可以繼續,並繼續)。對於現實生活中的例子,請考慮libstdC++的'std :: vector' – milleniumbug

+0

@milleniumbug - 這個繼承層次中沒有任何東西表明它是用於「技巧」的。如果是這樣,這個問題應該這樣說,以獲得更合適的答案。 –

回答

39

充分利用GrandParent構造私人和Parent朋友。

class GrandParent 
{ 
    friend class Parent; 
    private: 
    GrandParent() {} 
    // ... 
}; 

或者,您可以通過使析構函數私人權衡的GrandParents多態性破壞:

class GrandParent 
{ 
    friend class Parent; 
    private: 
    virtual ~GrandParent() {} 
}; 

// Invalid Destruction: 
GrandParent* p = new Parent; 
... 
delete p; 
+0

可能是最簡單的方法。 +1 –

+0

這裏唯一不足的地方是'朋友'是一個整體解決方案。我想不出任何更好的,但... – rubenvb

+0

我會試一試!非常感謝 – pacorrop

0

另一種方法來解決這個問題的方法是使用「模板神奇」。如果你試圖改變父類祖父母

#include <type_traits> 

class Child : public Parent 
{ 
}; 

static_assert(std::is_base_of<Parent, Child>::value, "Child must derive Parent"); 

,編譯器給你錯誤

+0

是的,我同意你的看法。 – LmTinyToon

+0

考慮到這一點,它可以擴展到更可靠的事情。如果OP的方法使用'T *'的參數和SFINAE檢查,T'從'GrandParent'派生,*它們可以包含'T'從'Parent'派生的'static_assert',以拒絕任何派生自'Parent'。但這只是讓我想到:OP想要完成什麼?在這種情況下,更簡單更安全的方法是首先將其限制爲「Parent」,而不用擔心其他'GrandParent'派生的類。 – hvd

+0

我不明白你有點想過。 – LmTinyToon