Учитывая базовые и производные классы, как показано ниже:
База:
class AA
{
public:
AA() = default;
virtual void print() const { std::cout << aa << "\n";}
private:
std::string aa = "AA";
};
Выведено:
class BB : public AA
{
public:
BB() = default;
virtual void print() const override {std::cout << bb << "\n"; }
private:
std::string bb = "BB";
};
Первая попытка:
int main()
{
AA aa; BB bb;
AA& //r = aa; r.print();
r = bb;
r.print();
return 0;
}
Результат был именно тем, что я ожидал:
BB
Press <RETURN> to close this window...
Но вторая попытка, когда //
был удален:
int main()
{
AA aa; BB bb;
AA& r = aa; r.print();
r = bb;
r.print();
//!^^^^^^^^^^--why wasn't the print in derived class called?
return 0;
}
Выход был:
AA
AA
Press <RETURN> to close this window...
Как указано выше, почему не было print
определяется в производном классе, вызываемом при выполнении второго r.print()
?
Потому что выражение r = bb
в точности эквивалентно aa = bb
, Оператор присваивания просто копирует части bb
известно AA
класс в aa
объект.
Другими словами, после назначения, r
еще указывает на aa
, который является примером AA
, Оно делает не указать на BB
экземпляр в любом смысле.
Ссылка никогда не может изменить к какому объекту она относится, поэтому ожидаемое поведение не может быть достигнуто с помощью ссылок. Чтобы получить полиморфизм, который вы ищете, вы должны использовать указатели:
AA* p = &aa;
p->print();
p = &bb;
p->print();
Из-за этого:
r = bb;
Вышеупомянутое утверждение не связывает (перепривязывать?) Ссылку r
в bb
, Вместо этого он копирует AA
части bb
в aa
который является объектом, на который ссылается r
,
Чтобы проверить вышеупомянутое утверждение, вот пример: http://coliru.stacked-crooked.com/a/00d20990fe0ddd26