什么事对象切片:

c++在将一个派生类转换为基类的过程中,派生类的一部分将被基类接收不到,只能留下基类大小的对象。


传值调用的切片:


#include<iostream>usingnamespacestd;classBase{public:virtualvoidfunc1(){cout<<"Base::func1"<<endl;}virtualvoidfunc2(){cout<<"Base::func2"<<endl;}private:inta;};classDerive:publicBase{public:virtualvoidfunc1(){cout<<"Derive::func1"<<endl;}virtualvoidfunc3(){cout<<"Derive::func3"<<endl;}virtualvoidfunc4(){cout<<"Derive::func4"<<endl;}private:intb;};typedefvoid(*FUNC)();voidPrintVTable(int*VTable){cout<<"虚表地址>"<<VTable<<endl;for(inti=0;VTable[i]!=0;++i){printf("第%d个虚函数地址:0X%x,->",i,VTable[i]);FUNCf=(FUNC)VTable[i];f();}cout<<endl;}voidfunction(Baseb){b.func1();}voidTest1(){Baseb1;Derived1;int*VTable1=(int*)(*(int*)&b1);int*VTable2=(int*)(*(int*)&d1);PrintVTable(VTable1);PrintVTable(VTable2);function(d1);}intmain(){Test1();system("pause");}



再拷贝的过程中发生了切片,在调用构造函数的时候初始化VPTR指向基类的VTABLE,并且只拷贝了对象的基类部分,所以最后就变成了一个基类的对象。

如果要防止这种现象的发生,只需把基类定义成纯虚函数就可以了。




将派生类的指针传递给基类

#include<iostream>usingnamespacestd;classBase{public:virtualvoidfunc1(){cout<<"Base::func1"<<endl;}virtualvoidfunc2(){cout<<"Base::func2"<<endl;}private:inta;};classDerive:publicBase{public:virtualvoidfunc1(){cout<<"Derive::func1"<<endl;}virtualvoidfunc3(){cout<<"Derive::func3"<<endl;}virtualvoidfunc4(){cout<<"Derive::func4"<<endl;}private:intb;};typedefvoid(*FUNC)();voidPrintVTable(int*VTable){cout<<"虚表地址>"<<VTable<<endl;for(inti=0;VTable[i]!=0;++i){printf("第%d个虚函数地址:0X%x,->",i,VTable[i]);FUNCf=(FUNC)VTable[i];f();}cout<<endl;}voidfunction(Base*b){b->func1();b->func2();}voidTest1(){Baseb1;Derived1;int*VTable1=(int*)(*(int*)&b1);int*VTable2=(int*)(*(int*)&d1);PrintVTable(VTable1);PrintVTable(VTable2);function((Base*)&d1);}intmain(){Test1();system("pause");}



解释:

在将派生类的指针传给基类之后,就将派生类的大小看作是积累的大小,所以就只能访问基类的大小,由于没有发生构造函数,所以VPTR还是派生类的。