max*_*yne 38 c++ inheritance compiler-errors
这是一个面试问题.考虑以下:
struct A {};
struct B : A {};
A a;
B b;
a = b;
b = a;
Run Code Online (Sandbox Code Playgroud)
为什么b = a;抛出错误,虽然a = b;完全没问题?
Joh*_*itb 62
因为隐式声明的复制赋值运算符B隐藏了隐式声明的复制赋值运算符A.
所以对于线b = a,只有在operator=的B是一个候选人.但是它的参数有类型B const&,不能通过A参数初始化(你需要一个向下转换).所以你得到一个错误.
use*_*016 24
因为每个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;
Run Code Online (Sandbox Code Playgroud)
在你的榜样,没有属性someInt,也没有anotherInt,所以它可以工作.但无论如何编译器都不会允许它.
确实a B是a A,但是a A不是a B,但是当你使用指针或对As和Bs的引用时,这个事实才直接适用.这里的问题是你的赋值运算符.
struct A {};
struct B : A {};
Run Code Online (Sandbox Code Playgroud)
相当于
struct A {
A& operator=(const A&);
};
struct B : A {
B& operator=(const B&);
};
Run Code Online (Sandbox Code Playgroud)
所以当你在下面分配时:
A a;
B b;
a = b;
Run Code Online (Sandbox Code Playgroud)
a可以使用参数of来调用赋值运算符on b,因为a B是a A,因此b可以作为a传递给赋值运算符A&.请注意,a赋值运算符只知道a中的数据,A而不知道a中的东西B,因此B中不属于A的任何成员都会丢失 - 这称为"切片".
但是当你试图分配时:
b = a;
Run Code Online (Sandbox Code Playgroud)
a是类型A,不是a B,因此a无法将B&参数与b赋值运算符匹配.
你会认为b=a应该只调用继承A& A::operator=(const A&),但事实并非如此.赋值运算符B& B::operator=(const B&)隐藏了将继承的运算符A.它可以通过using A::operator=;声明再次恢复.