【C++】设计一个不能被继承的类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wei_cheng18/article/details/81043858

设计一个类,不能被继承

在继承体系中:

基类public成员 基类protected成员 基类private成员 概括
public继承 仍为public成员 仍为protected成员 不可见 非私有成员访问属性不变
protected继承 变为protected成员 变为protected成员 不可见 非私有成员变为子类的protected成员
private继承 变为private成员 变为private成员 不可见 非私有成员变为子类的private成员
  • 我们知道派生类在构造对象时,会先调用其基类的构造函数,然后再调用派生类的构造函数。
  • 由上表可以发现,不管是哪种继承方式,peivate的成员均是不可见的,所以,如果我们把基类的构造函数和析构函数设计为私有的,那么派生类就不能调用基类的构造函数了,自然基类就不能被继承了。
  • 但是这样的话,这个基类也不能实例化了。我们可以想到通过静态方法,通过一个静态方法来返回类的实例,另一个静态方法来释放该对象。代码如下:
// 基类不能被继承,同时也解决了实例化的问题,但是这样却只能在堆上分配内存
class AA
{
private:
    AA(){ cout << "AA()" << endl; }
    ~AA(){ cout << "~A()" << endl; }
public:
    static void test(AA* a)
    {
        cout << "AA::test()" << endl;
    }
    static AA* construct(int n)
    {
        AA *a = new AA();
        a->_a = n;
        return a;
    }
    static void destroy(AA* aa)
    {
        delete aa;
    }
private:
    int _a;
};
class BB : public AA
{
};
void test()
{
    //BB b;
    AA* a = AA::construct(3);
    AA::test(a);
    AA::destroy(a);
}

有什么办法可以让类既不能被继承,又可以在栈上和堆上都能创建对象呢?不妨考虑一下友元

  • 先创建一个基类A,将其构造函数和析构函数都声明为私有的;
  • 我们要求的不能被继承的类B声明为A的友元类,这样B可以访问A类的构造函数和析构函数,B可以正常构造;
  • 同时还需要让类B虚拟继承A类,此时B类的子类C在构造对象时,会直接调用A类的构造函数,但是由于友元关系是不能被继承的,所以,C类调用A类的构造函数会报错,也就是说C类不能成功构造出对象,所以,B类是不可以被继承的。代码如下:
template <class T>
class A
{
    friend T;
private:
    int a;
    A()
    {
        cout << "A()" << endl;
    }
};

class B :public virtual A<B>
{
public:
    B()
    {
        cout << "B()" << endl;
    }
};

class C :public B
{
public:
    C()
    {
        cout << "C()" << endl;
    }
};

int main()
{
    B b;
    C c;
    return 0;
}
  • 这里需要说明的是:我们设计的不能被继承的类B对基类A的继承必须是虚继承,这样一来C类继承B类时会去直接调用A的构造函数,而不是像普通继承那样,先调用B的构造函数再调用A的构造函数;

  • C类直接调用A类的构造函数,由于A类的构造函数是私有的,而B是A的友元,C类不是A的友元,友元关系不会继承,因此会编译报错。

    • 除此之外,在C++11中已经像Java一样有了final关键字,被final修饰的虚函数(只能是虚函数)不能被重载,被final修饰的类不能被继承。
class A
{
public:
    virtual void foo() final
    {
        cout << "A" << endl;
    }
};

class B final : public A
{
public:
    //virtual void foo()//不能重写final函数
    //{
    //  cout << "B" << endl;
    //}
};

class C : public B // B类不能被继承
{

};
int main()
{
    B b;
    A &a = b;
    a.foo();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wei_cheng18/article/details/81043858