C++ Object slice

来源:互联网 发布:西门子plc300仿真软件 编辑:程序博客网 时间:2024/05/02 04:39

第一次遇到这个名词(Object slice)在meyers的Effective STL中。有一条忠告:
不要尝试使用STL容器,管理多态的类对象。类似:

class Base{public:virtual void fun(){cout << "Base" << endl;}};class Derived1 : public Base {public:virtual void fun(){cout << "Derived1" << endl;}};class Derived2 : public Base {public:virtual void fun(){cout << "Derived2" << endl;}};void main(){    vector<Base> vb;    Derived1 d1;    Derived2 d2;    vb.push_back(d1);    vb.push_back(d2);    vb[0].fun();    vb[1].fun();}

以上两次调用fun(),输出结果均为”Base”。原因就是在vb.push_back时发生了“object slice“。
换句话说,如果向基类对象建立一个容器中插入派生类对象,那么当对象放入容器的时候对象的派生部分不会被复制进容器。

注:可以看出STL管理对象的方式,无论是将对象放入容器,还是从容器中拿出对象(当然不包括operator[]),都是以复制的方式。即,如果insert或push_back(obj),放入容器的不是obj自己,而是obj的一个拷贝。

再说回Object slice,《Inside the C++ Object Model》中介绍是为什么会产生Object slice。简单的说就是,当你将一个派生类对象复制给基类对象时,为了保证内存空间的正确性,编译器只能将派生类对象切割,填充到基类对象的内存空间中(同时,虚表不会被重新赋值)。派生部分就是被切割的那部分。

相同道理,以下代码也会发生object slice:

void main(){    Base bs;    Derived1 dv1;    bs = dv1; // dv1会被slice    bs.fun(); // 会输出 Base}