dynamic_cast pointer from derived to base throws access violation error

Dec 28, 2010 at 12:07pm
Hi all,

I am not very sure of the exact mechanism that dynamic_cast uses, however the present code behavior is beyond my comprehension. It appears to me to have got to do something with access of vtable, yet please let me know what you think is wrong with the behavior:

class base {
int i,j;
public:
base(){}
base(int _i,int _j):i(_i),j(_j){}
virtual void show() {std::cout<<"Base"<<i<<j;}

};

class derived:public base
{
int i,j;
public:
derived(int _i,int _j):i(_i),j(_j){}
void show() {std::cout<<"Derived"<<i<<j;}

};

int main()
{
derived *d_ptr=dynamic_cast<derived*>(new base(1,2));
d_ptr->show();// This point throws access violation error


return 0;
}


However, if I replace dynamic_cast with static_cast, this code piece works fine. Replacing with static_cast I get following output:

Base12


Which is right, considering the virtual function mechanism. Then whey is the first case, not working and throwing access violation error. Your comments please.
Dec 28, 2010 at 12:36pm
In your code you try to use object of the base class through the interface of the derived class. This is like asking a bicycle with manual propulsion to perform like a motor bike. You can only do it the other way around. You can use object of the derived class through the interface of the base class.

Specifically, in your code new base(1,2) creates object of the base class. Then dynamic_cast<derived*>(new base(1,2)) tries to switch to the interface of the more powerful derived class. It can not, so it returns null pointer. Then d_ptr->show(); fails with access violation, because it calls function on a null pointer. Using static_cast instead permits, incorrectly, upgrading the interface to derived. In this case, d_ptr->show(); calls the function void derived::show() on object of dynamic type base. derived::show tries to access derived::i and derived::j. But d_ptr is actually pointing at object of class base. So, only base::i and base::j are present and those are different from the aforementioned. Basically, the function show reads random stuff from the memory after the object, but the program finishes execution, for what its worth.

The proper way to use casting, similar to your code:
1
2
base *b_ptr=dynamic_cast<base*>(new derived(1,2));
b_ptr->show();


There are other problems with your code. In the constructor for derived, you don't initialize the variables i and j from your base class. The variables with the same name from your derived class hide the ones from the base class, but use separate storage. What I mean is, you don't have to reintroduce variables from your base class into your derived class.

EDIT: for what its worth, you don't even really need dynamic_cast here, so base *b_ptr=static_cast<base*>(new derived(1,2)); is ok and better.
Last edited on Dec 28, 2010 at 2:27pm
Dec 28, 2010 at 1:12pm
Here is an excerpt taken from C++ from the ground Up (3rd Edition)


dynamic_cast
Perhaps the most important of the new casting operators is the dynamic_cast. The
dynamic_cast performs a run-time cast that verifies the validity of a cast. If at the
time dynamic_cast is executed, the cast is invalid, then the cast fails. The general
form of dynamic_cast is shown here:

dynamic_cast<target-type> (expr)
Here, target-type specifies the target type of the cast, and expr is the expression being
cast into the new type. The target type must be a pointer or reference type, and the
expression being cast must evaluate to a pointer or reference. Thus, dynamic_cast
may be used to cast one type of pointer into another, or one type of reference into
another.

The purpose of dynamic_cast is to perform casts on polymorphic types. For example,
given two polymorphic classes B and D, with D derived from B, a dynamic_cast
can always cast a D* pointer into a B* pointer. This is because a base pointer can
always point to a derived object. But, a dynamic_cast can cast a B* pointer into
a D* pointer only if the object being pointed to actually is a D object. In general,
dynamic_cast will succeed if the pointer (or reference) being cast is a pointer (or
reference) to either an object of the target type or an object derived from the target
type. Otherwise, the cast will fail.
If the cast fails, then dynamic_cast evaluates to
null if the cast involves pointers. If a dynamic_cast on reference types fails, a
bad_cast exception is thrown.
Dec 29, 2010 at 12:15pm
Thank you both guys! This code was more to understand the nuances, thanks for making it so clear!
Topic archived. No new replies allowed.