Jump to content
  • Advertisement
Sign in to follow this  
indigox3

dynamic_cast question

This topic is 4774 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Anyone know if its possible for a dynamic_cast to return NULL when the object you are casting really is of the type you are casting to? ie class A {} class B : public A {} B b; A* a = (A*)&b; B* c = dynamic_cast< B* > ( a ); this should be okay since "a" really is a B object. Sometimes its returning NULL on me, when it shouldn't. Also according to the VS.Net debugger, putting a watch on the "a" variable really does show it to be a B object.

Share this post


Link to post
Share on other sites
Advertisement
If your class has no virtual functions then calling dynamic_cast on one of its pointers is bad mojo.

Share this post


Link to post
Share on other sites
If by 'sometimes' you mean with some classes in the heirarchy and not others, you need to figure out what classes actually fail, and see what's different about them.

Dynamic_cast can also fail if RTTI is turned off..

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
If your class has no virtual functions then calling dynamic_cast on one of its pointers is bad mojo.


What-who-how-why? Makes sense, but do you have a reference to back that up?

Share this post


Link to post
Share on other sites
Quote:
Original post by Kuladus
Quote:
Original post by SiCrane
If your class has no virtual functions then calling dynamic_cast on one of its pointers is bad mojo.


What-who-how-why? Makes sense, but do you have a reference to back that up?

The C++ Programming Language Special Edition, section 15.4.1:

"A dynamic_cast requires a pointer or a reference to a polymorphic type in order to do a down-cast or a crosscast."

A class must have a vtable in order to successfully call dynamic_cast on it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kuladus
Quote:
Original post by SiCrane
If your class has no virtual functions then calling dynamic_cast on one of its pointers is bad mojo.


What-who-how-why? Makes sense, but do you have a reference to back that up?


Here's a reference: attempting to dynamic_cast from a base without a virtual function to a derived class generates a _compiler error_ using GCC:

class foo {};
class bar : public foo {};

int main () {
bar b;
foo * f = &b;
dynamic_cast< bar * >( f );
}





**** Incremental build of configuration Debug for project test.24 ****

make -k all
'Building file: ../main.cc'
g++ -O0 -g3 -Wall -c -fmessage-length=0 -omain.o ../main.cc
../main.cc: In function `int main()':
../main.cc:7: error: cannot dynamic_cast `f' (of type `class foo*') to type `class bar*' (source type is not polymorphic)
make: *** [main.o] Error 1
make: Target `all' not remade because of errors.
Build complete for project test.24


Example provided uses MinGW's GCC 3.4.2, compiled using the Managed Make C++ Project feature of the Eclipse IDE (3.0.2)

That is, the posters example fails to compile on my system. If your class is indeed polymorphic and you are getting a null pointer, it is because (in approximate likelyhood of chance): it is not of the correct type, or you have memory corruption of some sort, or your compiler needs a bugfix, or your CPU is failing (prehaps due to overheat?), or quantum mechanics are interfering with the normal operation of your computer.

Share this post


Link to post
Share on other sites
What: polymorphic type requirements for valid RTTI.
Who: there is no 'who' unless you talk to you code AND it talks back.
How: dynamic_cast relies on polymorphic types and RTTI.
Why: because that's what the spec says. Doesn't matter if it's logical or if you agree with it.


If you want a real world example of how dynamic_cast works and is actually implemented look at the source code for the G++ (GNU C++ compiler) runtime library. Understanding even ONE implementation of dynamic_cast can give you a great amount of insight into how it works.

[edit: RTTI and polymorphic types were skewed in 'How']

Share this post


Link to post
Share on other sites
If I had to implement dynamic_cast in a compiler, I'd just CMP the object's vtable pointer to the compiler-known vtable pointer for the type in question, return the object if they match or NULL otherwise. I wouldn't even have to have an extra RTTI switch.

Same restriction: you would have to use it on types that actually have a virtual table.

Share this post


Link to post
Share on other sites
Let's try a little "accidental" memory stomping experiment.


#include "conio.h"
#include "stdio.h"
#include "memory.h"

class TestA
{
public:
TestA() { a = 1; }
virtual int GetValue() { return a; }

int a;
};

class TestB : public TestA
{
public:
TestB() { a = 2; }
virtual int GetValue() { return 0; }
};

void main()
{
TestA *a1 = new TestA();
TestA *a2 = new TestB();

TestB *b1 = dynamic_cast<TestB*>(a1);
TestB *b2 = dynamic_cast<TestB*>(a2);

memcpy(a1, a2, 4); // copy the vtable pointer but not the data member.

TestB *b3 = dynamic_cast<TestB*>(a1);

printf("B1: 0x%08X\n", b1);
printf("B2: 0x%08X\n", b2);
printf("B3: 0x%08X\n", b3);

printf("A1->GetValue: %i\n", a1->GetValue());
printf("A2->GetValue: %i\n", a2->GetValue());
}







Output:


0x00000000
0x02DA2C80
0x02DA2C48
A1->GetValue: 0
A2->GetValue: 0


Ooosp! I just converted a TestA into a TestB.

This is in MSVC 7.1

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
The C++ Programming Language Special Edition, section 15.4.1:

"A dynamic_cast requires a pointer or a reference to a polymorphic type in order to do a down-cast or a crosscast."

A class must have a vtable in order to successfully call dynamic_cast on it.


Thanks for that reference. Almost sounds theological:

Strousup 15:14:1
"Thou needs a type polymorphic to dynamically cast thy way down!"

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!