如何防止一个类被继承
在C#中定义了关键字sealed,被sealed修饰的类是不能被继承的。同样在Java中也有关键字final表示一个类型不能被继承。然而在C++中却没有类似于sealed的关键字,C++11提供final关键字防止继承,因此就只能模拟实现它。这道题出自剑指offer,备受青睐的一道面试题。
- 防止被继承的思想
在C++中,子类的构造函数会自动调用父类的构造函数,子类的析构函数也会自动调用父类的析构函数。说到这你可能明白了,要想一个类不能被继承
,我们只要把它的构造函数和析构函数都定义为私有函数
,那么当一个类试图去继承
的时候,必然会由于调用构造函数和析构函数而导致编译错误。
下面就为大家介绍两种方法
来防止一个类被继承。
将构造函数设为私有函数
我们将构造函数和析构函数定义为私有函数,那么我们如何才能得到该类型的实例呢?我们可以通过定义公有的静态函数来创建和释放类的实例
。
#include <iostream>
using namespace std;
class SealedClass
{
public:
static SealedClass* GetInstance()
{
return new SealedClass();
}
static void DeleteInstance(SealedClass* _Instance)
{
delete _Instance;
}
private:
SealedClass()
{}
~SealedClass()
{}
};
class Derive :public SealedClass
{
public:
Derive()
{}
~Derive()
{}
};
int main()
{
system("pause");
return 0;
}
发现连编译都通过不了,说明 ·这个类是不能被继承
的,但是这样的类让人总感觉使用起来不方便,比如我们只能得到位于堆上的实例
,而得不到栈上的实例。
使用虚拟继承
使用虚拟继承就会弥补上述的缺点
,我们可以在堆上或栈上
创建实例,当然我们不仅将派生类声明为基类的友元
,而且还引入了虚拟继承
的特性,具体我们先看代码:
#include <iostream>
using namespace std;
template<class T>
class MakeSealed
{
friend class SealedClass;
private:
MakeSealed()
{}
~MakeSealed()
{}
};
class SealedClass :virtual public MakeSealed<SealedClass>
{
public:
SealedClass()
{}
~SealedClass()
{}
};
int main()
{
system("pause");
return 0;
}
现在编译运行肯定也不会出错了。尽管MakeSealed的构造函数与习惯函数都是私有的,但由于类SealedClass是它的友元类型,因此在SealedClass中调用MakeSealed的构造函数和析构函数就不会出错。
但是如果我们从派生类中继承一个类并创建它的实例
时,却不能编译通过,比如我们在派生类SealedClass中继承出类型Code:
class Code :public SealedClass
{
public:
Code()
{}
~Code()
{}
};
因为SealedClass是从类MakeSealed中虚拟继承的,在调用Code的构造函数时,会跳过SealedClass而直接调用MakeSealed的构造函数,但是Code不是类MakeSealed的友元函数,也就意味着不能访问人家的私有函数。
现在我们将虚拟继承的代码在linux的G++环境下跑一下看会发生什么:
g++环境下错误还是很多的,说明该程序的可移植性并不好
,这是因为gcc和g++编译器中还不支持模板参数类型作为友元函数。
C语言如何实现继承与多态
实现要求如下:
C 实现一个 struct A 和 stuct B 包含一个 int 成员 a 和 b,要求达到B 继承 A 的效果,也就是 B里面包含一个 A,并且能达到多态的效果,也就是一个 A* p 指向一个指向A 调的是 A 的函数,指向 B 调的是 B 的函数
具体效果如下C++演示:
#include <iostream>
using namespace std;
class A
{
public:
virtual void fun()
{
printf("A::fun()\n");
}
int _a;
};
class B:public A
{
public:
virtual void fun()
{
printf("B::fun()\n");
}
int _b;
};
int main()
{
A a;
B b;
A* p = &a;
p->fun();
p = &b;
p->fun();
return 0;
}
- 参考代码
#include <stdio.h>
typedef void(*FUN) ();//定义函数指针
struct A
{
FUN _f;//C语言的结构体不支持成员函数,只能用函数指针来实现“含有成员函数”
int _a;
};
struct B
{
struct A a;//C语言不支持继承,只能用嵌套结构体实现“B继承A”
int _b;
};
void funA()
{
printf("A::fun\n");
}
void funB()
{
printf("B::fun\n");
}
int main()
{
struct A a;
struct B b;
a._f = funA;
b.a._f = funB;
struct A* p = &a;
p->_f();
p = (struct A*)&b;
p->_f();
return 0;
}