Если вы не объявляете оператор копирования-присваивания в классе, компилятор объявит его для вас неявно. Неявно объявленный оператор копирования-присвоения будет скрывать все унаследованные операторы присваивания (читайте о «скрытии имени» в C ++), что означает, что любые унаследованные операторы присваивания станут «невидимыми» для неквалифицированного процесс поиска имени (что происходит, когда вы делаете b = c
), если вы не предпримете конкретные шаги, чтобы "показать их".
В вашем случае класс B
не имеет явно объявленного оператора копирования-присваивания. Это означает, что компилятор объявит
B& B::operator =(const B&)
неявно. Он будет скрывать оператор, унаследованный от A
. Линия
b = c;
не компилируется, потому что единственным кандидатом здесь является неявно объявленное выше B::operator =
(об этом вам уже говорил компилятор); все остальные кандидаты скрыты. А поскольку c
не может быть преобразовано в B&
, указанное выше назначение не компилируется.
Если вы хотите, чтобы ваш код компилировался, вы можете использовать using-объявление, чтобы показать унаследованный A::operator =
, добавив
using A::operator =;
к определению класса B
. Код теперь скомпилируется, хотя это не будет хорошим стилем. Вы должны иметь в виду, что в этом случае назначение b = c
вызовет A::operator =
, который назначает только части A
задействованных объектов. (Но, видимо, это ваше намерение.)
Кроме того, в подобных случаях вы всегда можете обойти скрытие имени, используя квалифицированную версию имени
b.A::operator =(c);