C ++ Dynami c cast, это не полиморфизм c? - PullRequest
0 голосов
/ 16 июня 2020

Когда я запускаю следующий код:

#include <iostream>

class Shape{
public:
};

class Square:public Shape
{
public:
};

class Circle:public Shape
{
    double r;
public:
    void SetRadious(double r)
    {
        std::cout << "R value:" << this->r <<std::endl;
        this->r=r;
    }
};

int main() {
    Shape * s = new Square();
    Circle* c= dynamic_cast<Circle*>(s);
    c->SetRadious(3.0);
    return 0;
}

, я получаю сообщение об ошибке:

'Shape' не является полиморфным c

Я читал об этом и узнал, что мне нужно написать какую-то виртуальную функцию. Но есть 2 вопроса:

1) Почему это необходимо, просто не имеет смысла требовать виртуальную функцию.

2) В этом случае многие сказали, что мне нужен виртуальный d'tor. Но почему стандартный d'tor не совсем подходит, в чем разница между d'tor по умолчанию и d'tor по умолчанию?

Ответы [ 2 ]

1 голос
/ 16 июня 2020

1) Зачем это нужно

Потому что язык так говорит. Так сказано, потому что это ограничение позволяет программам работать быстрее.

просто не имеет смысла требовать виртуальную функцию. меня. Если у вас нет виртуальной функции, я не вижу причин использовать динамическое c cast. Откровенно говоря, динамическое преобразование c довольно редко бывает полезно даже с полиморфными c классами.

2) В этом случае многие говорили, что мне нужен виртуальный d'tor Но почему вариант по умолчанию не будет полностью подходящим,

Потому что вариант по умолчанию не будет виртуальным.

В вашем примере происходит утечка памяти. Если бы вы попытались исправить утечку, выполнив delete s;, то поведение программы было бы неопределенным из-за отсутствия виртуального деструктора.

1 голос
/ 16 июня 2020

Иерархия классов, такая как та, которую вы представляете, не является polymorphi c из коробки.

И dynamic_cast требует, чтобы иерархия была полиморфной c.

Самый простой способ сделать полиморфизм иерархии c - это создать деструктор базового класса virtual:

class Shape {
    public:
        virtual ~Shape() = default;
};

Это также имеет преимущество, заключающееся в том, что теперь вы можете безопасно вызвать delete для указателя на Shape*, где тип Dynami c является одним из дочерних классов.

Обоснование этого состоит в том, что полиморфизм приводит к затратам времени выполнения, которые могут не потребоваться . Это также означает, что ваши классы теряют некоторые из своих C -подобных свойств, таких как тривиальные типы.

Обратите внимание, что после того, как вы представили этот виртуальный деструктор, значение c в

Circle* c = dynamic_cast<Circle*>(s);

будет nullptr, а поведение c->SetRadius(3.0); не определено.

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