实现一个无法被继承的C++类

如何写一个不能被继承,且能正常使用的类,下面提出三种思路。

C++11 的final关键词

类被final修饰,不能被继承。

class A1 final {};
class B1 : A1 {}; // "B1":无法从"A1"继承,因为它已被声明为"final"

更多关于C++11 override 和 final

私有声明类的构造函数

一个类不能被继承,也就是说它的子类不能构造父类,这样子类就没有办法实例化整个子类从而实现子类无法继承父类。我们可以将一个类的构造函数声明为私有,使得这个类的构造函数对子类不可见,那么这个类也就不能继承了。

static函数

定义静态方法,在方法内部实现一个对象,然后返回它的指针。

class A{
private:
    A(int v){m_v = v;}
    ~A(){}

    int m_v;

public:
    void fun(){cout<<"The value is: "<<m_v<<endl;
    static A* getInstance(int v);
};



A* A::getInstance(int v){
    m_instance = new A(v);
    return m_instance;
}

int main(){
    A *f = A::getInstance(int v);
    f->fun();
}

上述方法存在以下问题,A test这样是不可行的,而且上面类设计是一种只可以创建堆对象,不可以创建栈对象的情况

友元

友元是不能被继承,一个类A声明为一个类B的友元类friend class A;之后,类A就可以任意访问类B的所有成员(公有的、保护的和私有的)。但是,如果一个类D继承自类B**class D: public B**,类B中的 友元关系并不会被继承,也就是说,类A是类B的友元但却不是类B的派生类D的友元。我们可以尝试使用友元。

class A{
private:
    A(int v){m_v = v;}
    ~A(){}

    int m_v;

public:
    void fun(){cout<<"The value is: "<<m_v<<endl;
    friend A* getInstance(int v); //该函数可以访问类A中的所有东西,但不能访问A的继承类
};



A* getInstance(int v){
    m_instance = new A(v);
    return m_instance;
}

int main(){
    A *f = A::getInstance(int v);
    f->fun();
}

上述方法存在以下问题,A test这样是不可行的,而且上面类设计是一种只可以创建堆对象,不可以创建栈对象的情况

关于静态函数与友元函数

三层结构

class Base{
private:
    Base(){};
    ~Base(){};
    friend class A;
};

// 类A虚继承类Base
class A: virtual public Base{
public:
    A(int v){m_v = v;} //等价于A(int v):Base(){m_v = v;}
    ~A(){};

    void fun(){cout<<"The value is:"<<m_v<<endl;}

private:
    int m_v;
};


class B : public A
{
public:
    B():A(10){}// 出错,因为虚继承的特性
    /* 如果Base类的构造函数为非private,应该是如下这样 B():Base(), A(10){} 但是因为Base()是Private的所以B是不能访问的 */
    ~B(){}
};

class A 是Base的friend,所以A可以调用Base的构造函数。

因为A虚继承了Base,往后所有继承A的子类,都必须自己实例化Base,以保证Base在对象中的唯一性。

如果我们让A类虚继承Base类,根据虚继承的特性,虚基类的构造函数由最终的子类负责构造。因此B如果要想继承A,它必须能够构造Base,这是不可能的!因此,我们的B也就终于成为了一个无法继承的类。关于虚继承

所以,B继承A后,需要自己调用虚继承的父类Base的构造函数。显然,B不是Base的友元,不能访问private中的构造函数。

本站公众号
   欢迎关注本站公众号,获取更多程序园信息
开发小院