0

When I run the following code:

#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;
}

I get an error saying:

'Shape' is not polymorphic

I read about that and found out that I need to write some virtual function But have 2 questions:

1) Why is this necessary, it just doen't make sense to require a virtual function.

2) In this case many said that I need virtual d'tor But why the default one won't be totally fine, what's the difference between default d'tor and the default one?

  • Does this answer your question? [C++: Why does a struct\class need a virtual method in order to be polymorphic?](https://stackoverflow.com/questions/5831863/c-why-does-a-struct-class-need-a-virtual-method-in-order-to-be-polymorphic) – Adrian Mole Jun 16 '20 at 12:56
  • It makes sense because (subtype) polymorphism has a cost that you don't want to pay if you're not making use of it, and you don't make use of it if you don't have virtual functions. – molbdnilo Jun 16 '20 at 13:02
  • 1
    Notice that even with polymorphism, a square is not a circle, so `c` would be nullptr, leading to UB when de-referencing it. – Jarod42 Jun 16 '20 at 13:06

2 Answers2

1

A hierarchy of classes such as the one you present is not polymorphic out of the box.

And dynamic_cast requires the hierarchy to be polymorphic.

The easiest way of making the hierarchy polymorphic is to make the destructor of the base class virtual:

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

That also carries the benefit of your now being able to safely call delete on a pointer to Shape* where the dynamic type is one of the child classes.

The rationale behind this is that polymorphism introduces a run-time expense that might not be required. It also means that your classes lose some of their C-like properties such as being trivial types.

Note that once you have introduced this virtual destructor, the value of c in

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

will be nullptr, and the behaviour of c->SetRadius(3.0); is undefined.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

1) Why is this necessary

Because the language says so. It says so, because this limitation allows the programs to be faster.

it just doen't make sense to require a virtual function.

It makes perfect sense to me. Unless you have a virtual function, I see no reason to ever use dynamic cast. Frankly, dynamic cast is quite rarely useful even with polymorphic classes.

2) In this case many said that I need virtual d'tor But why the default one won't be totally fine,

Because the default one won't be virtual.

Your example leaks memory. If you were to attempt to fix the leak by doing delete s;, then the behaviour of the program would be undefined due to the lack of virtual destructor.

eerorika
  • 232,697
  • 12
  • 197
  • 326