полиморфизм времени выполнения и dynamic_cast нуждаются в пояснении - PullRequest
0 голосов
/ 29 мая 2020

Мог бы ответить где-то еще, но не смог найти правильную фразу, чтобы спросить

, так что слушайте.

У меня базовый класс A с дочерними B и C; (полностью для целей обучения)

#include <iostream>

class A 
{ 
    public: 
        virtual void print () { std::cout<< "A::print()" << std::endl; } 
}; 

class B: public A 
{ 
    public: 
        void print () { std::cout<< "B::print()" << std::endl; } 
}; 

class C : public B 
{ 
    public: 
        void print () { std::cout<< "C::print()" << std::endl; } 
};

итак, в моем основном я объявил базовый указатель A* bptr; позже также объявлены дочерние B и C.

позже bPtr указал на B и вызвал print функцию, работающую должным образом; позже bPtr указал на C и вызвал функцию print, которая работает должным образом;

слышит код, нет проблем слышит.

int main()  
{
    A* bPtr;

    B b;
    C c;

    bPtr = &b;
    bPtr->print(); // prints B::print() - as expected;

    bPtr = &c;
    bPtr->print(); // prints C::print() - as expected;

}

слышать - это моя дилемма, я могу неправильно понять; теперь то, что я думал все эти дни, dynamic_cast также делает точно выше; но все по-другому, ИЛИ я делаю что-то не так. безопасный переход между базой и детским?

if ( B* b = dynamic_cast<B*>( bPtr ))
{
        b->print(); // still calls C::print() anyway;
}

1 Ответ

2 голосов
/ 29 мая 2020

Это поведение не имеет ничего общего с dynamic_cast.

Поведение виртуального вызова всегда будет зависеть от фактического типа времени выполнения значения. Во втором примере единственное, что на самом деле построено, - это C, поэтому все вызовы будут разрешаться в C, независимо от того, называете ли вы его A: A * a = bPtr или B: B * b = bPtr, он будет разрешен в C :: print (), потому что оператор new C конструирует фактическое значение как C.

Dynamic_cast просто будет приводить значение, данное к типу, указанному c, если это (a подтип) этого типа, или иначе вернуть nullptr. Таким образом, динамическое преобразование B * в C * завершится ошибкой и вернет nullptr, но в вашем случае вы преобразуете C * в один из его базовых типов, который всегда будет успешным и никогда не изменит само значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...