473,396 Members | 2,037 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

dynamic_cast between unrelated types

Hello,

first, I didn't find any reference to my question through googling.

dynamic_cast uses RTTI to determine if the cast expression is valid.
Invalid casts of pointers give a '0'-result. As it is the case in the
following example:

-----------------------------------------------------------
#include <iostream>

struct A {virtual void print() {std::cout << "A" << std::endl;}};
struct B {virtual void print() {std::cout << "B" << std::endl;}};
int main(int argc,char* argv[])
{
A* a = new A();
B* b = dynamic_cast<B*>(a);
if (b)
b->print();
else
std::cout << "b is 0" << std::endl;
return 0;
}
-------------------------------------------------------------

This compiles just fine with MS C++ 7, g++ 3.3.3. Running this tells me
(quite correctly) that "b is 0".

What I really don't get is - why isn't this detected at compile time? OK,
that's what static_cast does (replacing the dynamic_cast with a
static_cast in the example gives a nice compiler error).

Scott Meyers advises to prefer compile time errors to run time errors. So
naive reasoning tells me to prefer static_cast, whenever possible.

So here's the question: Can anybody tell me when to prefer dynamic_cast
to static_cast? Are there any possible situations where static_cast
doesn't really work and you have to use dynamic_cast?

Regards
Thomas
Jul 23 '05 #1
8 2568
* Thomas Lorenz:
Hello,

first, I didn't find any reference to my question through googling.

dynamic_cast uses RTTI to determine if the cast expression is valid.
Invalid casts of pointers give a '0'-result. As it is the case in the
following example:

-----------------------------------------------------------
#include <iostream>

struct A {virtual void print() {std::cout << "A" << std::endl;}};
struct B {virtual void print() {std::cout << "B" << std::endl;}};
int main(int argc,char* argv[])
{
A* a = new A();
B* b = dynamic_cast<B*>(a);
if (b)
b->print();
else
std::cout << "b is 0" << std::endl;
return 0;
}
-------------------------------------------------------------

This compiles just fine with MS C++ 7, g++ 3.3.3. Running this tells me
(quite correctly) that "b is 0".

What I really don't get is - why isn't this detected at compile time?
It probably is.

And with non-polymorphic types you'd get a compile time error.

With polymorphic types, however, the language allows this because the
pointer 'a' might be a pointer to the 'A' subobject of an object of a
class that inherits from both 'A' and 'B':

#include <iostream>

struct A {virtual void print() {std::cout << "A" << std::endl;}};
struct B {virtual void print() {std::cout << "B" << std::endl;}};
struct C: A, B {};

int main()
{
A* a = new C();
B* b = dynamic_cast<B*>( a );
if (b)
b->print();
else
std::cout << "b is 0" << std::endl;
return 0;
}
OK,
that's what static_cast does (replacing the dynamic_cast with a
static_cast in the example gives a nice compiler error).

Scott Meyers advises to prefer compile time errors to run time errors. So
naive reasoning tells me to prefer static_cast, whenever possible.
That's not naive, that's very good.

So here's the question: Can anybody tell me when to prefer dynamic_cast
to static_cast? Are there any possible situations where static_cast
doesn't really work and you have to use dynamic_cast?


When you don't know the types at compile time, and a virtual function doesn't
solve the problem (virtual functions perform safe downcasts for you).

Perhaps the most typical example is to apply an event E to an object O, where
you don't know whether O supports event E or not.

In such cases it's preferable to centralize the dynamic casts instead of
having such casts scattered around the code, and one way of centralizing them
is to use the "visitor pattern" (google).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #2
In general you use static_cast when you want to convert numeric data
types such as enums to ints or ints to floats, and you are certain of
the data types involved in the conversion. static_cast conversions are
not as safe as dynamic_cast conversions, because static_cast does no
run-time type check, while dynamic_cast does. A dynamic_cast to an
ambiguous pointer will fail, while a static_cast returns as if nothing
were wrong; this can be dangerous. Although dynamic_cast conversions
are safer, dynamic_cast only works on pointers or references, and the
run-time type check is an overhead.

Saurabh Aggrawal

Jul 23 '05 #3
"Saurabh Aggrawal" <ga*****@hotmail.com> wrote in
news:11**********************@z14g2000cwz.googlegr oups.com:
In general you use static_cast when you want to convert numeric data
types such as enums to ints or ints to floats, and you are certain of
the data types involved in the conversion. static_cast conversions are
not as safe as dynamic_cast conversions, because static_cast does no
run-time type check, while dynamic_cast does. A dynamic_cast to an
ambiguous pointer will fail, while a static_cast returns as if nothing
were wrong; this can be dangerous. Although dynamic_cast conversions
are safer, dynamic_cast only works on pointers or references, and the
run-time type check is an overhead.

Saurabh Aggrawal


OK, that's perfectly understandable. But why isn't dynamic_cast allowed
to do some type checking at compiletime, as static_cast does? My example
code provides the compiler with enough information to decide that the
cast won't work.

And I really can't envision a commonplace scenario containing a line like
DestType* dest = dynaic_cast<DestType*>(src);
where the compiler doesn't know about DestType. OK, DestType could be
void, but those are scenarios I reallly don't want to think about :)

Regards
Thomas
Jul 23 '05 #4
Thomas Lorenz schrieb:
"Saurabh Aggrawal" <ga*****@hotmail.com> wrote in
news:11**********************@z14g2000cwz.googlegr oups.com:

In general you use static_cast when you want to convert numeric data
types such as enums to ints or ints to floats, and you are certain of
the data types involved in the conversion. static_cast conversions are
not as safe as dynamic_cast conversions, because static_cast does no
run-time type check, while dynamic_cast does. A dynamic_cast to an
ambiguous pointer will fail, while a static_cast returns as if nothing
were wrong; this can be dangerous. Although dynamic_cast conversions
are safer, dynamic_cast only works on pointers or references, and the
run-time type check is an overhead.
Yes and no. There are situations when a static_cast on a class/struct
pointer or reference is needed and perfectly safe and so the overhead of
dynamic_cast is completely wasted. Limiting its use to basic types is a
little too strict.
OK, that's perfectly understandable. But why isn't dynamic_cast allowed
to do some type checking at compiletime, as static_cast does? My example
code provides the compiler with enough information to decide that the
cast won't work. Have you read Alf's reply? It shows one such example. A compiler error
in your example case would be logical, but not really worth the effort
given that in almost no real world code, the assignment to the source
pointer/reference is made in a place visible to the compiler at the
point of the cast, so it cannot check whether the conversion might
possibly succeed or not.
And I really can't envision a commonplace scenario containing a line like
DestType* dest = dynaic_cast<DestType*>(src);
where the compiler doesn't know about DestType. OK, DestType could be
void, but those are scenarios I reallly don't want to think about :)

As Alf wrote, the dynamic type of src could be convertible to DestType*
even if src's static type doesn't suggest it is.

Cheers,
Malte
Jul 23 '05 #5
Malte Starostik <ma***@starostik.de> wrote in
news:42********@olaf.komtel.net:

[snip]
There are situations when a static_cast on a class/struct
pointer or reference is needed and perfectly safe and so the overhead
of dynamic_cast is completely wasted. Limiting its use to basic types
is a little too strict.
Yes, that sounds very reasonable, and this is the path I've already
taken.

[snip] Have you read Alf's reply? It shows one such example. A compiler
error in your example case would be logical, but not really worth the
effort given that in almost no real world code, the assignment to the
source pointer/reference is made in a place visible to the compiler at
the point of the cast, so it cannot check whether the conversion might
possibly succeed or not.

No, obviously not ;) His example makes the behaviour of dynamic_cast
perfectly clear.

Thanks for all the help!
Thomas
Jul 23 '05 #6
Thomas Lorenz wrote:

Malte Starostik <ma***@starostik.de> wrote in
news:42********@olaf.komtel.net:

[snip]
There are situations when a static_cast on a class/struct
pointer or reference is needed and perfectly safe and so the overhead
of dynamic_cast is completely wasted. Limiting its use to basic types
is a little too strict.


Yes, that sounds very reasonable, and this is the path I've already
taken.

[snip]
Have you read Alf's reply? It shows one such example. A compiler
error in your example case would be logical, but not really worth the
effort given that in almost no real world code, the assignment to the
source pointer/reference is made in a place visible to the compiler at
the point of the cast, so it cannot check whether the conversion might
possibly succeed or not.

No, obviously not ;)


The problem is that the compiler can not *always* diagnose that.
Most compiler writers, and I am with them on that issue, think that
diagnosing a problem only *sometimes* creates a false sense of security.
Only if a potential problem can be analysed in each and every case, a
warning or an error is something to think about.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 23 '05 #7
"Saurabh Aggrawal" <ga*****@hotmail.com> wrote in
news:11**********************@z14g2000cwz.googlegr oups.com:
In general you use static_cast when you want to convert numeric data
types such as enums to ints or ints to floats, and you are certain of
the data types involved in the conversion. static_cast conversions are
not as safe as dynamic_cast conversions, because static_cast does no
run-time type check, while dynamic_cast does. A dynamic_cast to an
ambiguous pointer will fail, while a static_cast returns as if nothing
were wrong; this can be dangerous. Although dynamic_cast conversions
are safer, dynamic_cast only works on pointers or references, and the
run-time type check is an overhead.


OK, that's perfectly understandable. But why isn't dynamic_cast allowed
to do some type checking at compiletime, as static_cast does? My example
code provides the compiler with enough information to decide that the
cast won't work.

And I really can't envision a commonplace scenario containing a line like
DestType* dest = dynaic_cast<DestType*>(src);
where the compiler doesn't know about DestType. OK, DestType could be
void, but those are scenarios I reallly don't want to think about :)

Regards
Thomas
Jul 23 '05 #8
"Saurabh Aggrawal" <ga*****@hotmail.com> wrote in
news:11**********************@z14g2000cwz.googlegr oups.com:
In general you use static_cast when you want to convert numeric data
types such as enums to ints or ints to floats, and you are certain of
the data types involved in the conversion. static_cast conversions are
not as safe as dynamic_cast conversions, because static_cast does no
run-time type check, while dynamic_cast does. A dynamic_cast to an
ambiguous pointer will fail, while a static_cast returns as if nothing
were wrong; this can be dangerous. Although dynamic_cast conversions
are safer, dynamic_cast only works on pointers or references, and the
run-time type check is an overhead.

Saurabh Aggrawal


OK, that's perfectly understandable. But why isn't dynamic_cast allowed
to do some type checking at compiletime, as static_cast does? My example
code provides the compiler with enough information to decide that the
cast won't work.

And I really can't envision a commonplace scenario containing a line like
DestType* dest = dynaic_cast<DestType*>(src);
where the compiler doesn't know about DestType. OK, DestType could be
void, but those are scenarios I reallly don't want to think about :)

Regards
Thomas
Jul 23 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: alg | last post by:
dynamic_cast<> comes in play when to perform conversion from a pointer to a base class to a pointer to a derived class. I don't understand: 1. why this is so necessary since we can either use...
5
by: tthunder | last post by:
Hi @all, Perhaps some of you know my problem, but I had to start a new thread. The old one started to become very very confusing. Here clean code (which compiles well with my BCB 6.0 compiler)....
4
by: 0to60 | last post by:
I'm coding in MC++ and I'm using the System::Collections data structures to store my own objects. When I get something out of a hashmap, should I be using dynamic_cast or old C-style casting? In...
22
by: Boris | last post by:
I'm porting code from Windows to UNIX and ran into a problem with dynamic_cast. Imagine a class hierarchy with three levels: class Level2 derives from Level1 which derives from Base. If you look...
15
by: Grizlyk | last post by:
Hello. Returning to question of manual class type identification, tell me, for ordinary inheritance is C++ garantee that dynamic_cast<Derived*>(Base*) can be implemented similarly to ...
8
by: pietromas | last post by:
In the example below, why does the dynamic_cast fail (return NULL)? It should be able to cast between sibling classes ... #include <iostream> class A { public: virtual const int get()...
15
by: Bo Yang | last post by:
Hi, I can understand static_cast, reinterpret_cast and const_cast, they all work at compile time. But I can figure out how the C++'s dynamic- cast works? Could you please explain how for me?...
25
by: lovecreatesbea... | last post by:
Suppose I have the following three classes, GrandBase <-- Base <-- Child <-- GrandChild The following cast expression holds true only if pBase points object of type of ``Child'' or...
18
by: Eric | last post by:
Ok...this seems to be treading into some really esoteric areas of c++. I will do my best to explain this issue, but I don't fully understand what is happening myself. I am hoping that the problem...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.