Ответ 1
Краткая версия. Разрешение перегрузки не выбрало Base::operator=(Base)
. Он выбрал неявно объявленный Derived::operator=(const Derived &)
, который вызывает Base::operator=(Base)
, чтобы копировать-присваивать подобъект базового класса.
Длинная версия со стандартными кавычками:
Во-первых, оператор присваивания копий определен в стандарте в §12.8 [class.copy]/p17:
Пользовательский оператор присваивания копий
X::operator=
является нестатической нематричной функцией-членом класса X с точно одним параметром типаX
,X&
,const X&
,volatile X&
илиconst volatile X&
.
Во-вторых, если вы не предоставляете оператора присваивания копий, он всегда будет объявлен неявно. Из §12.8 [class.copy]/p18:
Если определение класса явно не объявляет назначение копии оператор, один объявляется неявно. Если определение класса объявляется конструктор перемещения или оператор назначения перемещения, неявно объявленный оператор назначения копирования определяется как удаленный; в противном случае определяется как дефолт (8.4). Последний случай устарел, если класс имеет объявленный пользователем конструктор копирования или объявленный пользователем деструктор. Неявно объявленный оператор назначения копирования для класс X будет иметь вид
X& X::operator=(const X&)
если
- каждый прямой базовый класс
B
ofX
имеет оператор присваивания копии, параметр которого имеет типconst B&
,const volatile B&
илиB
и- для всех нестатических членов данных
X
, которые имеют тип класса M (или его массив), каждый такой тип класса имеет назначение копии оператор которого имеет типconst M&
,const volatile M&
илиM
.В противном случае оператор неявно объявленного копирования будет иметь форма
X& X::operator=(X&)
Обратите внимание, что одним из результатов этих правил является то, что (§12.8 [class.copy]/p24):
Поскольку оператор присваивания копирования/перемещения неявно объявляется для класс, если он не объявлен пользователем, назначение копирования/переноса базового класса оператор всегда скрыт соответствующим оператором присваивания производный класс.
Другими словами, разрешение перегрузки никогда не может выбрать оператор присваивания копий Base
для назначения от одного Derived
к другому. Он всегда скрыт и даже не входит в набор функций-кандидатов.
Наконец, в §12.8 [class.copy]/p28 предусмотрено, что
Неявно определенный оператор присваивания копий/перемещений для неединичного класса X выполняет поэтапное копирование/перемещение назначения своих подобъектов.
В случае вопроса нет оператора присваивания копии для Derived
, поэтому он будет объявлен неявным образом как дефолт (поскольку Derived
не имеет объявленного пользователем конструктора перемещения или оператора назначения перемещения). Этот неявный оператор присваивания копии будет выбран с помощью разрешения перегрузки и выполняет назначение копии, среди прочего, подобъекта базового класса, который вызывает оператор присваивания копии, который вы определили для Base
.