C++ Object slice

第一次遇到这个名词(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
}

猜你喜欢

转载自blog.csdn.net/svp_Charles/article/details/78348152
今日推荐