平台:win7+VS2010
虚函数继承
虚函数是实现多态,异质列表的强大工具。主要原理是使用基类指针调用不同派生类的函数,使得同一函数可以有不同的实现效果。
PS:因为派生类指针一般长于基类指针,因此不建议使用派生类指针指向基类对象,否则可能会出现意想不到的错误。类似于类型转换时,长数据可以转换成短数据,但需要显示强制类型转换,而且长数据变成短数据可能造成数据丢失等错误。
#include <iostream>
using namespace std;
class Base
{
public:
virtual void fb(){ cout<<"Base::fb"<<endl;}
virtual void f(){}
};
class Derive:public Base
{
public:
void fb(){ cout<<"Derive::fb"<<endl;}
virtual void fd(){}
};
int main()
{
Derive d;
Base *p = &d;
p->fb();
d.fb();
return 0;
}
Base类的fb()函数不是虚函数时,运行结果为:
Base::fb
Derive::fb
Base类的fb()函数是虚函数时,运行结果为:
Derive::fb
Derive::fb
派生类继承了基类的虚函数表,但是和基类的虚函数表的地址不同,当派生类覆盖了基类中的虚函数时,这个虚函数在虚函数表中将替代为派生类的训函数地址,没有重写的虚函数仍保留基类的虚函数地址。
所以说,
非虚函数继承中,实现的是函数的重载(this指针不同),即在Base类中void fb()实际上是void fb(Base * const this ),而在Derive类中void fb()实际上是void fb( Derive * const this)。
虚函数继承中,实现的是函数的覆盖,Derive的fb()函数会取代Base 的fb()函数在虚表中的位置,从而实现基类指针调用子类函数实现版本的效果。
虚继承
虚继承是多继承中,为了解决一个类间接地多次继承一个基类而造成空间浪费和与设计模型不同的问题,而打的一个补丁。应用虚继承,多次被继承的基类数据在派生类中只有一份数据而不是多份。
PS:一般不建议让一个类继承多个类,类树会比较复杂,实现和调试也比较复杂。
虚继承类的构造函数、析构函数调用顺序如下:
#include <iostream>
using namespace std;
class A{
public:
A(){cout<<"create class A"<<endl;}
~A(){cout<<"drop class A"<<endl;}
};
class B:public virtual A{
public:
B(){cout<<"create class B"<<endl;}
~B(){cout<<"drop class B"<<endl;}
};
class C:public virtual A{
public:
C(){cout<<"create class C"<<endl;}
~C(){cout<<"drop class C"<<endl;}
};
class D:public virtual C,public virtual B{
public:
D(){cout<<"create class D"<<endl;}
~D(){cout<<"drop class D"<<endl;}
};
int main(){
D d;
return 0;
}
运行结果为:
create class A
create class C
create class B
create class D
drop class D
drop class B
drop class C
drop class A
虚继承不同于一般继承,会生成多一个指向父类数据的指针。如下图:
验证如下:
#include <iostream>
using namespace std;
class A{
virtual void fa();
};
class B:public virtual A{
virtual void fb();
};
class C:public virtual A{
virtual void fc();
};
class D:public virtual C,public virtual B{
virtual void fd();
};
class E:public virtual B{
virtual void fe();
};
class F:public virtual E{
virtual void ff();
};
int main(){
cout<<sizeof(A)<<endl;
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
cout<<sizeof(D)<<endl;
cout<<sizeof(E)<<endl;
cout<<sizeof(F)<<endl;
return 0;
}
运行结果为:
4
12
12
28
20
28