在 “切片” 中,您将派生类的对象分配给基类的实例,从而丢失了部分信息 - 其中一些信息被 “切片” 了。
例如,
class A {
   int foo;
};
class B : public A {
   int bar;
};因此,类型B的对象具有两个数据成员foo和bar 。 
然后,如果您要编写此代码:
B b;
A a = b;然后, b有关成员bar的信息丢失在a 。 
这里的大多数答案都无法解释切片的实际问题是什么。他们只说明切片的良性案例,而不说明危险的切片。像其他答案一样,假设您正在处理两个类A和B ,其中B (公开地)从A派生。 
在这种情况下,C ++ 允许您将B的实例传递给A的赋值运算符(也传递给副本构造函数)。之所以可行,是因为B的实例可以转换为const A& ,这是赋值运算符和复制构造函数所期望的参数。 
B b;
A a = b;那里什么都没发生 - 您要求A的实例,它是B的副本,而这正是您所得到的。当然, a不会包含b的某些成员,但是应该如何?毕竟是A ,而不是B ,所以它甚至都没有听说过这些成员,更不用说能够存储它们了。 
B b1;
B b2;
A& a_ref = b2;
a_ref = b1;
//b2 now contains a mixture of b1 and b2!您可能会认为b2将是b1的副本。但是,a, 不是 !如果检查它,您会发现b2是弗兰肯斯坦主义的生物,它由b1一些块( B从A继承的块)和b2一些块(仅B包含的块)组成。哎哟! 
发生了什么?好吧,默认情况下,C ++ 不会将赋值运算符视为virtual 。因此,行a_ref = b1将调用A的赋值运算符,而不是B的赋值运算符。这是因为,对于非虚函数, 声明的类型(即A& )确定要调用哪个函数,而不是实际的类型(应为B ,因为a_ref引用B的实例)。现在, A的赋值运算符显然只知道A声明的成员,因此它将仅复制那些成员,而保持B添加的成员不变。 
仅分配给对象的一部分通常没有什么意义,但是不幸的是,C ++ 没有提供内置的方法来禁止这种情况。但是,您可以自己滚动。第一步是使赋值运算符为virtual 。这样可以确保始终调用的是实际类型的赋值运算符,而不是声明的类型。第二步是使用dynamic_cast验证分配的对象是否具有兼容类型。第三步是在(受保护的!)成员assign()进行实际分配,因为B的assign()可能要使用A的assign()复制A的成员。 
class A {
public:
  virtual A& operator= (const A& a) {
    assign(a);
    return *this;
  }
protected:
  void assign(const A& a) {
    // copy members of A from a to this
  }
};
class B : public A {
public:
  virtual B& operator= (const A& a) {
    if (const B* b = dynamic_cast<const B*>(&a))
      assign(*b);
    else
      throw bad_assignment();
    return *this;
  }
protected:
  void assign(const B& b) {
    A::assign(b); // Let A's assign() copy members of A from b to this
    // copy members of B from b to this
  }
};请注意,为纯粹方便起见, B的operator=协变量会覆盖返回类型,因为它知道它正在返回B的实例。 
如果您具有基类A和派生类B ,则可以执行以下操作。 
void wantAnA(A myA)
{
   // work with myA
}
B derived;
// work with the object "derived"
wantAnA(derived);现在,方法wantAnA需要derived的副本。但是, derived的对象无法完全复制,因为类B可以发明不在其基类A其他成员变量。 
因此,要调用wantAnA ,编译器将 “分片” 派生类的所有其他成员。结果可能是您不想创建的对象,因为
A (类B所有特殊行为都丢失了)。