Yes, I know that downcast using dynamic_cast
can't compile if the Base
is not polymorphic, but my problem is not about this.
class Base {
public:
virtual void bar()
{
cout << "bar\n";
}
};
class Derived: public Base {
public:
void foo()
{
cout << "foo\n";
}
};
int main()
{
Base *pb;
Derived *pd;
pb = new Derived; //Base* points to a Derived object
pd = dynamic_cast<Derived*>(pb);
pd->foo(); //outputs foo
pb = new Base; //Base* points to a Base object
pd = dynamic_cast<Derived*>(pb);
pd->foo(); //outputs foo, too. Why?
}
I thought when pb = new Derived;
, pb
actually points to a Derived
object lies in heap. After pd = dynamic_cast<Derived*>(pb);
, pd
also points to that Derived
object, so pd->foo()
should be OK.
But when pb = new Base;
, what pb
points to is a Base
object in heap, then after pd = dynamic_cast<Derived*>(pb);
, how could pd->foo()
works? Did dynamic_cast
turn the Base
object in heap into a Derived
object?
[edit] SyntaxIf the cast is successful, dynamic_cast returns a value of type new-type. If the cast fails and new-type is a pointer type, it returns a null pointer of that type. If the cast fails and new-type is a reference type, it throws an exception that matches a handler of type std::bad_cast.
Consider this simple hierarchy: class Base { public: virtual ~Base() { } }; class Derived : public Base { }; Trying to downcast Base* p to Derived* is possible using dynamic_cast<Derived*>(p) . I used to think dynamic_cast works by comparing the vtable pointer in p to the one in a Derived object.
The dynamic_cast operator ensures that if you convert a pointer to class A to a pointer to class B , the object of type A pointed to by the former belongs to an object of type B or a class derived from B as a base class subobject.
static_cast − This is used for the normal/ordinary type conversion. This is also the cast responsible for implicit type coersion and can also be called explicitly. You should use it in cases like converting float to int, char to int, etc. dynamic_cast −This cast is used for handling polymorphism.
You're running into undefined behavior. You should check the return type of dynamic_cast
.
pd = dynamic_cast<Derived*>(pb);
This returns null, and you call a function on a NULL
pointer. Anything can happen.
In C++, each instance of a class has its own version of datatypes, but all classes share the same function in memory (other than for inline functions). In your case, when you say something like:
pd->foo();
You are essentially calling Derived::foo
, which is a function in memory and the compiler knows where it is. The thing is, it is not dependent on pd
at all. However, if you had something like this:
class Derived : public Base {
private:
int a;
public:
Derived() { a = 100; }
void foo() {
std::cout<<a<<std::endl;
}
};
Then, pd->foo()
will cause a Segmentation fault. Here, your dynamic cast has failed and when Derived::foo
is called, it is passed 0
as the this
object. It was fine in the previous case, as the this
object was never used. However, in the second case, it is used and hence, causes a Segmentation fault.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With