重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
什么事对象切片:
目前成都创新互联已为近千家的企业提供了网站建设、域名、虚拟空间、网站托管、服务器托管、企业网站设计、缙云网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
c++在将一个派生类转换为基类的过程中,派生类的一部分将被基类接收不到,只能留下基类大小的对象。
传值调用的切片:
#includeusing namespace std; class Base { public: virtual void func1() { cout << "Base::func1" << endl; } virtual void func2() { cout << "Base::func2" << endl; } private: int a; }; class Derive :public Base { public: virtual void func1() { cout << "Derive::func1" << endl; } virtual void func3() { cout << "Derive::func3" << endl; } virtual void func4() { cout << "Derive::func4" << endl; } private: int b; }; typedef void(*FUNC) (); void PrintVTable(int* VTable) { cout << " 虚表地址>" << VTable << endl; for (int i = 0; VTable[i] != 0; ++i) { printf(" 第%d个虚函数地址 :0X%x,->", i, VTable[i]); FUNC f = (FUNC)VTable[i]; f(); } cout << endl; } void function(Base b) { b.func1(); } void Test1() { Base b1; Derive d1; int* VTable1 = (int*)(*(int*)&b1); int* VTable2 = (int*)(*(int*)&d1); PrintVTable(VTable1); PrintVTable(VTable2); function(d1); } int main() { Test1(); system("pause"); }
再拷贝的过程中发生了切片,在调用构造函数的时候初始化VPTR指向基类的VTABLE,并且只拷贝了对象的基类部分,所以最后就变成了一个基类的对象。
如果要防止这种现象的发生,只需把基类定义成纯虚函数就可以了。
将派生类的指针传递给基类
#includeusing namespace std; class Base { public: virtual void func1() { cout << "Base::func1" << endl; } virtual void func2() { cout << "Base::func2" << endl; } private: int a; }; class Derive :public Base { public: virtual void func1() { cout << "Derive::func1" << endl; } virtual void func3() { cout << "Derive::func3" << endl; } virtual void func4() { cout << "Derive::func4" << endl; } private: int b; }; typedef void(*FUNC) (); void PrintVTable(int* VTable) { cout << " 虚表地址>" << VTable << endl; for (int i = 0; VTable[i] != 0; ++i) { printf(" 第%d个虚函数地址 :0X%x,->", i, VTable[i]); FUNC f = (FUNC)VTable[i]; f(); } cout << endl; } void function(Base* b) { b->func1(); b->func2(); } void Test1() { Base b1; Derive d1; int* VTable1 = (int*)(*(int*)&b1); int* VTable2 = (int*)(*(int*)&d1); PrintVTable(VTable1); PrintVTable(VTable2); function((Base*)&d1); } int main() { Test1(); system("pause"); }
解释:
在将派生类的指针传给基类之后,就将派生类的大小看作是积累的大小,所以就只能访问基类的大小,由于没有发生构造函数,所以VPTR还是派生类的。