貌似有些同学还不太明白这个,我试着用c代码描述c++类相关的一些实现方式。
设类abc,bc继承于a,都有个虚函数f(),析构函数为虚
c++代码
//---------A
struct a{
a(){
}
void f(){
printf("class a\n";
}
virtual ~a(){
}
};
struct b:public a{
b(){
}
virtual void f(){
printf("class b\n";
}
virtual ~b(){
}
};
struct c:public a{
c(){
}
void f(){
printf("class b\n";
}
virtual ~c(){
}
};
main(){
a* p=new a;
p->f();
delte p;
p=new b;
p->f();
delete p;
}
//C语言描述,语法问题请无视,否则要写一大堆typedef定义类型
设c_a()为a构造函数 d_a()为a的析构函数,vt_a为a的虚函数表结构
b,c类似
先构造结构
struct vt_a{
destructFun_ptr;
virtual_f_ptr;
};
这里b和c的vtable和a结构一致,没有扩充函数
vt_b{
vt_a father;//
//扩充的其他函数在下面
};
struct a{
vt_a vtable;
//a的其他成员变量
...
};
struct b{
a father_a;
//b的其他成员变量
};
c和b类似
//生成虚函数表
vt_a vtable_a={
d_a,vf_a_f;
};
vt_b vtable_b={
d_b,vf_b_f;
};
vt_c vtable_c={
d_c,vf_c_f;
};
编译
p=new a;
p->f();
delete p;
编译为
//第一句
p=new_op(sizeof(a));//对应的new函数(全局,局部),可以认为就是malloc
a* pa==(a*)p;
pa->vtable=vtable_a; //对不同的子类,vtable指向不同的表
pa->c_a(pa);
//第二句
pa->vtable->virtual_f_ptr(pa);//这里就是多态的实现方法(vtable的不同,实现调用子类的虚函数)
//第3句
pa->vtable->destructFun_ptr(pa);
delete_op(pa);//对应的delete函数,可以认为就是free
///最后是链式析构的实现方式
d_a(){
//自定义的代码
...
}
d_b()
{
//自定义的代码
...
//编译器添加
d_a(this);
}
这就是链式析构的原理
编译时一个类的父类是一定可以确定的,可以这么认为,一个子类的析构函数调用后,this就退化为父类的类型了,这时继续调用父类的析构函数(编译器实现),直到没有父类为止。
多重继承时情况和单继承类似,只是内存布局不同,子类和父类指针转换时可能会有偏移值。