c++对象切片
什么事对象切片:
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还是派生类的。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。