面试题28:不能被继承的类

在C#中定义了关键字sealed,被sealed修饰的类不能够被继承。在Java中同样也有关键字final表示一个类不能被继承。C++11提供final关键字使得类不能够被继承。

那么,如何自己实现一个不被继承的类?常规的解法是,把类的构造和析构函数都设置为private即可,然后公有派生;这是因为子类访问不到父类私有属性。这使用了C++构造派生类实例时会自动先调用父类构造函数的特性,同样析构的顺序和构造的顺序相反。

这种做法可行,但是我们只能得到位于栈上或堆上的实例(通过类内的static方法创建实例)!如果在堆和栈都能创建实例呢?且看下面的描述:

如果一个类D虚拟继承父类B,那么类D的派生类的实例被创建时会跳过类B的构造函数,直接调用类D的构造函数。根据这一特点,我们可以把D的构造函数和析构函数都设置为private,即可实现类D不能被继承!

但D公有继承自类B,那么D的构造函数和析构函数会分别调用父类B的构造和析构函数,而此时父类B的构造和析构函数均为private,如何使得派生类D拥有父类B私有成员的访问权限呢?

使用友元和模板!!!!完整代码如下,代码中的注释说明了一起!

template<class T>
class MakeSealed
{
    friend T;// ① 友元类,使得友元T拥有访问private成员的权限
private:// ② 把类的构造函数和析构函数为private,那么该类不能够被继承!!!
    // 因为它的派生类不具有访问私有构造函数和析构函数的权限;但是假如派生类是该父类的友元,那么该类便可派生!
    MakeSealed() {
        std::cout << "MakeSealed ctor called!" << std::endl;
    }
    ~MakeSealed() {
        std::cout << "MakeSealed dtor called!" << std::endl;
    }
};

// SealedClass为MakeSealed父类的友元,否则SealedClass的构造函数和析构函数因不可访问父类构造和析构函数而提示错误!
class SealedClass : virtual/* ③ 不能被派生的SealedClass必须虚继承MakeSealed */ public MakeSealed<SealedClass>
{
public:
    SealedClass() {
        std::cout << "SealedClass ctor called!" << std::endl;
    }

    ~SealedClass() {
        std::cout << "SealedClass dtor called!" << std::endl;
    }
};

class Try : public SealedClass
{
public:
    Try() {// VS2015提示错误:“MakeSealed::MakeSealed()[其中T=SealedClass]不可访问”
        std::cout << "Try ctor called!" << std::endl;
    }


    ~Try() {// VS2015提示错误:“MakeSealed::~MakeSealed()[其中T=SealedClass]不可访问”
        std::cout << "Try ctor called!" << std::endl;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值