2016-05-29 36 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