如何禁止公共继承但允许私有(和受保护)继承

时间:2015-05-04 19:20:06

标签: c++ c++11 inheritance

C ++ 11引入了关键字final以禁止未来覆盖或禁止继承。可以使用它的最常见示例是针对不打算用作基类的类的情况(例如具有非虚拟析构函数)。但是,有时我们可能希望在两个类(即private继承)之间存在 is-implemented-in-terms-of 关系,而不是是-a 关系(public继承)。但是,final禁止这两种类型的继承。

我的问题如下:是否有任何方法允许private继承但禁止public继承(可能不是直接,但至少可以“模拟”它)?在这种情况下,即使我们使用具有非虚析构函数的类也不会有任何问题,因为我们不能通过指向base的指针直接使用派生类,所以我们应该没问题。

我正在考虑这样的代码:

class Base /*final*/ {}; // making it final prohibits both private and public inheritance

class PrivateDerived: private Base{}; // this should work

class PublicDerived: public Base{}; // this shouldn't

int main()
{
    PrivateDerived prvd;
    PublicDerived  pubd; // this should not compile

    // Base* pBase = new PrivateDerived; // doesn't work, so we are ok
}

2 个答案:

答案 0 :(得分:4)

有趣的问题!如果你不介意放弃析构函数的琐事,我认为以下工作可以做到:

#include <type_traits>

template <typename T>
class Base {
protected:
    ~Base() {
        static_assert(!std::is_convertible<T*,Base*>::value, "Invalid use of public inheritance.");
    }    
};

class Derived : public Base<Derived> {
};

int main() {
    Derived d;
}

上面的代码无法编译:{{1​​}}触发,因为static_assert可转换为Derived*。但是,如果将继承更改为Base<Derived>*protected,则代码将编译。

不幸的是,用户仍然可以用脚射击自己:

private

答案 1 :(得分:0)

我不确定这是否是您正在寻找的,或者这对您的情况是否有帮助。然而,我将证明多态行为。

受保护的构造函数抽象类

class BaseProtected {
// ----- Member Variable Section -----
public: 
    // There Shouldn't Be Public Variables In A Base Class Unless 
    // That Is The Behavior You Are Looking For - Keep In Mind
    // Every Inherited Class & Outside Class Can Change Them.
protected:
    // Member Variables Here To Be Shared With Each Derived Class
private:
    // Member Variables Here To Be Used By Base Class Only

// ----- Member Function Section -----
public:
    virtual ~BaseProtected(); // Virtual Destructor 
    void somefunc() const; // Common Function Between All Derived Class
    virtual void allDerivedMustImplement() const; = 0 // Purely Virtual  

protected:
    // Default Constructor - Can Not Declare An Instance Of Base Class
    BaseProtected(); // Abstract Class         

   // Protected Functions Shared Between Classes
   // Protected Functions That Are Purely Virtual If Needed

private:
    // Private Functions Used By Base Class Only

}; // BaseProtected

具有可能继承的派生类

class DerivedWithPossibleInheritance : public BaseProtected {
// ----- Member Variable Section -----
public:
    // Public Member If Giving Free Access   
protected:
    // Protected Members If Being Inherited From
private:
    // Private Members Unique To This Derived Class

// ----- Member Function Section ----- 
public:
    DerivedWithPossibleInheritance(); // Default Constructor
    virtual ~DerivedWithPossibleInheritance(); // Virtual Destructor

    void uniqueFunctionForThisClass() const;
    void allDerivedMustImplement() const override;

private:
    // Private Functions Unique To This Class

}; // DerivedWithPossibleInheritance 

无法继承的派生类

class DerivedClassCanNotBeInheritedFrom sealed : public BaseProtected {
// ----- Member Variable Section -----
public: 
    // Public Members Variables
protected:
    // Should Not Have Member Variables Here For This Class Can Not Be Inherited from
private:
    // Private Members Variables

// ----- Member Function Section ------
public:
    DerivedClassCanNotBeInheritedFrom(); // Default Constructor
    virtual ~DerivedClassCanNotBeInheritedFrom(); // Default Virtual Destructor

    void anotherUniqueFunctionForThisClass() const;
    void allDerivedMustImplement() const override;

protected:
    // There Should Not Be Any Functions Here This Can Not Be Inherited From

private:    
    // Private Member Functions Here

}; // DerivedClassCanNotBeInheritedFrom

我在这里演示的是使用继承和多态时密封的关键词。如果您不希望从中派生类,请使用sealed关键字。

对于声明任何基类,独立类或具有私有构造函数的单例类,需要使用friend关键字。这里有很多类型的实现可以用来显示它们,但是防止类继承的概念是相同的。我个人没有使用关键字final,但我使用了关键字密封,它非常好用。

我没有使用除了public之外的类的继承:所以,就保护或私有继承而言,回答你的问题不是我真正熟悉的。但也许使用密封关键字可能对您有所帮助。