C++实现一个不能被继承的类

方法一:构造方法私有化 + static公有方法访问构造方法

最直观的解决方法就是将其构造函数声明为私有的,这样就可以阻止子类构造对象了。但是这样的话,就无法构造本身的对象了,就无法利用了

既然这样,我们又可以想定义一个静态方法来构造类和释放类

#include<iostream>
using namespace std;
class A{
  public:
     static A * Construct(int n){
          A *pa = new A;
          pa->num = n;
          cout<<"num is:"<<pa->num<<endl;
          return pa;
     }
     static void Destruct(A * pIntance){
         delete pIntance;
         pIntance = NULL;
     }
     private:
             A(){}
             ~A(){}
     public:
             int num;
 };
 
 int  main(){
     A *f = A::Construct(9);
     cout<<f->num<<endl;
     A::Destruct(f);
     return 0;
}

按照理论分析,这样做确实可以做到防止被继承

注意:又有一个新的问题,这种实现原理和单例模式一模一样,就是只能在堆上创建,无法再栈上实现这个类

这就是私有的构造函数的局限性

方法二:基类构造方法私有化 + 友元派生类 + 虚继承

主要思想,设计一个模板辅助类Base,将构造函数声明为私有的;再设计一个Base的友元类FinalClass,并且将FinalClass虚继承自Base

#include <iostream>

using namespace std;

template <typename T>
class Base {
    friend T;
private:
    Base() {
        cout << "base" << endl;
    }
    ~Base() {}
};

class FinalClass : virtual public Base<FinalClass> {
    // 一定注意,必须是虚继承,只有虚继承才能让派生类完成虚基类的构造
    // 普通继承下派生类不用负责最顶层基类的构造
public:
    FinalClass() {
        cout << "FinalClass()" << endl;
    }
};

class C :public FinalClass {
public:
    C() {}     //继承时报错,无法通过编译
};


int main() {
    FinalClass b;      //B类无法被继承
    //C c;
    return 0;
}

为什么一定要使用虚继承?

如果不使用虚继承,C构造时调用FinalClass 的构造函数,FinalClass的构造函数能调用Base的构造函数,C成功继承FinalClass类,这不是我们想要的

如果使用虚继承,由于此时的Base是虚基类,C中出现Base成员的地方都会用vbptr替换,并且把Base成员移动到C对象内存的最末尾处,由C类的构造函数负责初始化Base的数据成员,因此构造C的构造函数必须直接调用Base的构造函数,而C无法访问Base的构造函数,C继承FinalClass失败

之所以使用虚继承,是想让派生类直接访问虚基类的构造函数,如果不能访问虚基类的构造函数,当前类就无法构造对象

方法三:使用final关键字

class FinalClass final {
public:
    FinalClass() {}
};
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bugcoder-9905

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值