为什么赋值给基类是有效的,但是赋值给派生类的编译错误?
这是一个面试问题。 考虑以下:
struct A {}; struct B : A {}; A a; B b; a = b; b = a;  为什么b = a; 抛出一个错误,而a = b; 是完美的吗? 
 因为B的隐式声明的复制赋值运算符隐藏了B的隐式声明的复制赋值运算符。 
 所以对于b = a ,只有B的operator=是候选人。 但是它的参数有B const&型B const& ,不能用A参数初始化(你需要向下)。 所以你得到一个错误。 
因为每个B是一个A,但不是每个A都是一个B.
编辑下面的评论,使事情更清楚一点(我修改你的例子):
 struct A {int someInt;}; struct B : A {int anotherInt}; A a; B b; /* Compiler thinks: B inherits from A, so I'm going to create a new A from b, stripping B-specific fields. Then, I assign it to a. Let's do this! */ a = b; /* Compiler thinks: I'm missing some information here! If I create a new B from a, what do I put in b.anotherInt? Let's not do this! */ b = a; 
 在你的例子中, someInt和anotherInt没有属性,所以它可以工作。 但编译器不会允许它。 
 确实, B是A ,但A不是B ,但是这个事实只有在你使用指针或者引用A和B的时候才是直接适用的。 这里的问题是你的赋值操作符。 
 struct A {}; struct B : A {}; 
相当于
 struct A { A& operator=(const A&); }; struct B : A { B& operator=(const B&); }; 
所以当你在下面分配时:
 A a; B b; a = b; 
  a上的赋值运算符可以用b的参数来调用,因为B是A ,所以b可以作为A&被传递给赋值运算符。 请注意,赋值操作符只知道A的数据,而不知道B ,所以B中不属于A的任何成员都会丢失 – 这就是所谓的“分片”。 
但是当你试图分配:
 b = a; 
  a是typesA ,它不是B ,所以a不能和B&的赋值运算符相匹配。 
 你会认为b=a应该调用inheritance的A& A::operator=(const A&) ,但事实并非如此。 赋值运算符B& B::operator=(const B&)隐藏了将从Ainheritance的运算符。 它可以using A::operator=;来重新恢复using A::operator=; 宣言。 
我已经改变了你的结构的名字,使原因很明显:
 struct Animal {}; struct Bear : Animal {}; Animal a; Bear b; a = b; // line 1 b = a; // line 2 
显然,任何熊也是一种动物,但不是每一只动物都可以被认为是一只熊。
因为每个B“isa”A,B的任何实例也必须是A的一个实例:根据定义,它具有与A的任何其他实例相同顺序的相同成员。将b复制到a中会丢失特定于B的成员,但完全填充满足A的要求的结构的成员。另一方面,将a复制到b可能会使b不完整,因为B可能具有比A更多的成员。在这里很难看到,因为A和B都不是有任何成员,但这就是为什么编译器允许一个分配,而不是其他。
请记住,如果没有显式声明的复制赋值操作符,将隐式声明和定义任何类(并且结构是C ++中的类)。
 对于struct A它将具有以下签名: 
 A& A::operator=(const A&) 
它只是执行其子对象的成员分配。
 a = b; 是可以的,因为B将与A::operator=(const A&)的const A&参数相匹配。 由于只有A的成员被“成员分配”给目标,所以B中不属于A任何成员都会丢失 – 这就是所谓的“切片”。 
 对于struct B ,implcit赋值运算符将具有以下签名: 
 B& B::operator=(const B&) 
 b = a; 不正确,因为A不会匹配const B&参数。 
如果我接受采访的话,我会用一点哲学的方式来解释。
 a = b; 
 是有效的,因为每个B包含A作为其一部分。 所以可以从B提取A 但是, A不包含B 因此b在A内找不到B ; 这就是为什么, 
 b = a; 
是无效的。
  [类似地, void*可以在任何Type*find,但Type*不能在void*find(因此我们需要一个cast)。]