首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何禁止公共继承但允许私有(和受保护)继承

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

Stack Overflow用户
提问于 2015-05-05 03:20:06
回答 2查看 802关注 0票数 17

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

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

我想的代码是这样的:

代码语言:javascript
复制
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
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-05 18:17:44

有趣的问题!如果你不介意放弃析构函数的琐碎之处,我认为下面的方法就可以完成任务:

代码语言:javascript
复制
#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;
}

上面的代码无法编译:因为Derived*可以转换为Base<Derived>*,所以会触发static_assert。但是,如果将继承更改为protectedprivate,则代码将进行编译。

不幸的是,用户仍然可以搬起石头砸自己的脚:

代码语言:javascript
复制
class Bad : public Base<Derived> {
};
票数 4
EN

Stack Overflow用户

发布于 2015-05-05 10:43:32

我不确定这是你想要的,还是对你的情况有帮助。但是,我将演示多态行为。

受保护的构造函数抽象类

代码语言:javascript
复制
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

具有可能继承的派生类

代码语言:javascript
复制
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 

无法继承的派生类

代码语言:javascript
复制
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。如果您不想让您的类派生自,则使用sealed关键字。

对于声明任何基类、独立类或具有私有构造函数的单例类,都需要使用friend关键字。这里涉及到许多类型的实现来展示它们,但是防止类被继承的概念是相同的。就我个人而言,我没有使用关键字final,但我使用了关键字sealed,它工作得非常好。

我没有使用过除public类以外的其他类的继承:因此,从受保护或私有继承的角度回答您的问题并不是我真正熟悉的事情。但是也许使用关键字sealed可能会对您有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30038266

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档