dynamic_cast, static_cast and reintrepret_cast

Hello. My problem is not with what these operators do, but why they exist. I cant really think of a situation where you would need to use any of them. Could somebody help me out? Because I cant really understand them without knowing their applications
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct base{
   //...
   virtual void DoSomething()=0;
};

struct derivedOne : base{
   //...
   virtual void DoSomething(){//...}
   void DoDerivedType1Action();
};

struct derivedTwo : base{
   //...
   virtual void DoSomething(){//...}
   void DoDerivedType2Action();
};

int main(){
   base * pB = new derivedOne;
   pB->DoSomething(); //OK
   pB->DoDerivedType1Action();//Error
   derivedOne * pD1 = dynamic_cast<derivedOne *>(pB); //Cast 
   if(pD1 )
      pD1->DoDerivedType1Action(); //now ok.
}


If you know what they do, can you surmise why they exist?
Last edited on
Right, but isn’t it better performance-wise to have DoDerivedType1Action and DoDerivedType2Action as pure virtual methods in base?
Typical use of dynamic_cast:

Downcast to a child type if you are not sure whether or not the object actually is of that child type.

1
2
3
4
5
6
7
8
9
void Person::InteractWithAnimal( Animal* animal )
{
  // this person will pet any animal
  animal->GivePets();

  // but will only give treats to dogs
  Dog* dog = dynamic_cast<Dog*>(animal);
  if(dog)
    dog->GiveDoggieTreat();




Typical uses of static_cast:

1) Convert one basic type to another. Such as double to int.
1
2
3
double money = 15.63;

int cents = static_cast<int>( money * 100 );



2) Downcast (similar to dynamic_cast) when you are SURE the object is of the desired type (higher performance than dynamic_cast).


Typical use of reinterpret_cast:

Cast between completely unrelated pointer types.

1
2
3
4
5
6
7
8
double somearray[] = {1.2, 3.14, 5.6};

// I want to see the raw data of that array as a string of bytes
uint8_t* rawdata = reinterpret_cast<uint8_t*>(somearray);

//   note that static_cast would fail here because this is not a 
//   compatible type.  reinterpret_cast is basically a way to tell the compiler
//   "shut up, I'm sure I know what I'm doing, trust me". 
Right, but isn’t it better performance-wise to have DoDerivedType1Action and DoDerivedType2Action as pure virtual methods in base?


There is no right or wrong answer. How do you measure performance. Actual CPU efficiency, memory usage, maybe development cost, or ease of maintainability?

Strictly speaking, having to cast to 'some type' incurs a runtime check(with dynamic cast, compile time check with static, and no check with reinterpret), so there is overhead, but in today's world it is negligent. If you cant afford such overhead, you will know, because you will be using profilers on a daily basis (Ok so maybe you wont be using profiler but are still not using casts, you will know).

You asked why they exist, did you mean something about performance? Or are you asking because their is the availability of the C style casts?(Which I advise against)
Well, I just wasn’t sure of their purpose in terms of classes, because you can just use pure virtual methods, and I'm still not entirely sure. For example, in clanmjc's example, you could just implement the base struct like this:
1
2
3
4
5
6
struct base{
   //...
   virtual void DoSomething()=0;
   virtual void DoDerivedType1Action()=0;
   virtual void DoDerivedType2Action()=0;
};
and have no need for the dynamic_cast operator or its over-heads at all.
Last edited on
@Owain
Doing it that way each derived class must implement the pure functions. So DerivedType1 has a DoDerivedType2Action() which, to me at least, doesn't make much sense.
That's a good point. I didn’t realize that.
Or are you asking because their is the availability of the C style casts?(Which I advise against)
Why do you advise against C-style casts?
Last edited on
Why do you advise against C-style casts?
They are like using reinterpret_cast for all your casts, which carries it's own risk. It's also much easier to read code with the C++ casts, you can read the explicit types of casts. As well as finding them in code is much easier... try doing a search for (int) in a solution vs static_cast<int&> or something along those lines.
Watch the videos: All Castings Considered

Part I:
http://www.youtube.com/watch?v=lglGKxNrLgM

Part II:
http://www.youtube.com/watch?v=UfrR1nNfoeY
clanmjc wrote:
[C-style casts] are like using reinterpret_cast for all your casts, which carries it's own risk.


Ehhh.. C-style casts are not the same as reinterpret_cast....


static_cast, const_cast, dynamic_cast, and reinterpret_cast all do distinctly different things.

1) static_cast converts between types, doing "hidden" pointer math where appropriate
2) const_cast removes type qualifiers without doing any type conversion.
3) dynamic_cast does the job of static_cast, but does runtime checks to ensure the cast is good
4) reinterpret_cast forcibly converts between types, without doing any hidden conversion or pointer math. The data is taken "as-is" and simply reinterpretted (hence the name).


These are 4 distinct jobs that do different things. So in C++ you're given 4 different tools, one to address each situation.

C-style cast is sort of an all-in-one that meshes all of them together (except for dynamic_cast, which a C style cast cannot perform).

When doing a C-style cast.... whether you get a static, a const, or a reinterpret cast depends entirely on the context, so it's less verbose and more prone to "gotcha"s. What's worse, the vast majority of "gotchas" will surface as runtime bugs instead of compiler errors.
Last edited on
I know I was just saying they are like reinterpret and might as well be thought of that way because of the inherent possibility it performs a reinterpret, choosing the LCD.
C-style casts actually much more closely resemble static_cast, since that's what they do probably about 90+% of the time. So I wouldn't advise thinking of them as reinterpret_cast... especially to someone who is already confused about the difference between types of casts.

AFAIK the only time they perform a reinterpret_cast is when doing a static_cast would be illegal.
AFAIK the only time they perform a reinterpret_cast is when doing a static_cast would be illegal.
I think your right, and is all the reason I need to "think" of them as reinterpret_cast. As a defensive coder, this is just how I think and... It's just personal preference really. I think we can all agree C++ cast advantages far outweigh using C-style casts and that was really what I was trying to get at with the OP.
Topic archived. No new replies allowed.