Это правда, что 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
знает только о данных, которые находятся в A
, а не о вещах в B
, поэтому любые члены B, которые не являются частью A, теряются - это известно как 'нарезка'.
Но когда вы пытаетесь присвоить:
b = a;
a
имеет тип A
, который не является B
, поэтому a
не может сопоставить параметр B&
с оператором присваивания b
.
Можно подумать, что b=a
должен просто вызывать унаследованный A& A::operator=(const A&)
, но это не так. Оператор присваивания B& B::operator=(const B&)
скрывает оператор, который будет унаследован от A
. Его можно восстановить снова с помощью using A::operator=;
декларации.