Почему динамическое связывание не ведет себя так, как ожидалось?

Учитывая базовые и производные классы, как показано ниже:

База:

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()?

0

Решение

Потому что выражение r = bb в точности эквивалентно aa = bb, Оператор присваивания просто копирует части bb известно AA класс в aa объект.

Другими словами, после назначения, r еще указывает на aa, который является примером AA, Оно делает не указать на BB экземпляр в любом смысле.

Ссылка никогда не может изменить к какому объекту она относится, поэтому ожидаемое поведение не может быть достигнуто с помощью ссылок. Чтобы получить полиморфизм, который вы ищете, вы должны использовать указатели:

AA* p = &aa;
p->print();

p = &bb;
p->print();
3

Другие решения

Из-за этого:

r = bb;

Вышеупомянутое утверждение не связывает (перепривязывать?) Ссылку r в bb, Вместо этого он копирует AA части bb в aa который является объектом, на который ссылается r,

Чтобы проверить вышеупомянутое утверждение, вот пример: http://coliru.stacked-crooked.com/a/00d20990fe0ddd26

1

По вопросам рекламы [email protected]