一、使用混入技术实现的简单范例
成员函数的虚拟性可以通过特殊的继承来表达,我们先看看一个简单的范例,通过混入技术来实现:
//基类
template<typename... T>
class Base:public T... {
public:
void myfunc(){
std::cout << "Base::myfunc()执行了\n";
}
};
template<typename... T>
class Derived : public Base<T...> {
public:
void myfunc() {
std::cout << "Derived::myfunc()执行了\n";
}
};
这里我们运用的混入技术:派生类继承基类的模板。然后我们写两个类,一个为空类,一个为具有虚函数的类:
//空类,用于测试虚拟性
class A {
};
//具有虚函数的类
class AVir {
public:
virtual void myfunc() {};
};
我们这里观察一下继承链:
1.Base类继承了T…类,可以看做是一个多继承
2.Derived类继承Base<T…>类,由于Base类是多继承的,因此Derived类也间接是多继承的。
然后,我们在测试函数内写入以下的代码:
void Test1() {
//普通函数
Base<A> *pb1 = new Derived<A>;
pb1->myfunc();
//虚函数
Base<AVir>* pb2 = new Derived<AVir>;
pb2->myfunc();
}
这里我们观察一下单继承的情况:
由于
T
T
T类型,这里的
A
V
i
r
AVir
AVir类,具有虚成员函数,因此继承链的所有类都具有虚成员函数,因此当基类调用派生类函数的时候会发生多态,而
A
A
A类不具有虚成员函数,因此调用的是自身的函数。
我们运行一下观察:
可以发现,虚函数的存在体现的多态
从结果中可以看出,我们给
B
a
s
e
Base
Base类提供一个带有虚函数的类,那么就可以让
B
a
s
e
Base
Base中的同名函数
m
y
f
u
n
c
myfunc
myfunc变为虚函数,这就是所谓的“用参数化的方式表达成员函数的虚拟性”。
同样的,我们使用多继承看看:
void Test2() {
Base<A, AVir> *pb1 = new Derived<A, AVir>;
Base<AVir, A>* pb2 = new Derived<AVir, A>;
pb1->myfunc();
pb2->myfunc();
}
运行结果:
实际上,只要继承列表中存在一个类具有虚成员函数,那么就会发生多态,这根本上是因为不管是多继承还是单继承,只要存在虚函数的基类,那么在派生类就会存在虚函数指针,在运行时发生多态。
由于对象模型不是泛型与模板关注的重点,因此更多细节请自行查找资料。