2014-01-22 2 views
0

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

Базовые:

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

ответ

3

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

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

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

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

p = &bb; 
p->print(); 
+0

Так на самом деле оператор 'г = bb' изменил значение' aa' путем копирования суб - объект объекта 'bb' к нему, не так ли? –

+0

Я не уверен, что я следую терминологии «предмет объекта», но да: 'r = bb' просто запускает' aa.AA :: operator = (bb) ', что, в свою очередь, копирует' AA'-части 'bb' в' AA'. – user4815162342

+0

Извините за мою глупую орфографию, я должен был написать как подобъект ... и не знаю, почему я не могу на ваше имя user4815162342 .. –

1

Из-за этого:

r = bb; 

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

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

+0

http://coliru.stacked-crooked.com/ - это кажется довольно удобным thx man! –

+1

@Alan.W Это довольно «стандартный» онлайн-компилятор здесь, в [теге: C++], хотя вы можете найти больше на странице [C++ wiki] (http://stackoverflow.com/tags/c%2b%2b/info). –

Смежные вопросы