设计一个类,不能被继承
在继承体系中:
基类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;
}