Dynamic cast vs static cast

hi guys,

again I'm watching one of Jamie kings videos ( https://www.youtube.com/watch?v=0AuPWXuBmyo ), in one aspect it's helpful in another it's not, the aspect in which it's not is that he leaves out some explanations

@4:30 you can see that it prints derived1function() and the number 5,

I understand why 5 is being printed, basically we have statically casted a base pointer b to a Derived1 pointer, even though b is pointing to a derived2 object in memory. the reason 5 is being printed is that that variable happens to be in the place of the other variable and by chance both variables are int's so 5 will be printed,

but my question is how come derived1function is executed?? derived2 does not have a function called derived1function? ....

how is this done? since the object in memory is a derived2 object how is the derived1 function even called in the first place since that object in memory will not have a derived1function?

thanks


Last edited on
I don't understand.
I'm supposed to, like, watch a video?

I've heard of pictures of code, generally frowned upon, but this is the next level. :-)
might be interesting but I'll post the code, I just thought somebody could have a quick look at the source and possibly recognise what is meant.

let me show you an example with my own code, the code is slightly different than in the video

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
26
27
28
29
30
31
32
33
34
35
36
37
class Employee{

 public:
    virtual void f(){}

};

class Manager : public Employee{

   public:
       int data;
       int dataTwo;

       void printData(){
           cout << "print data from manager" << data << endl;
       }

};

class CEO : public Employee{

  public:
      int moreData;
      double d;


};


int main()
{

    Employee* e = new CEO;
    Manager* m = static_cast<Manager*>(e);
    m->printData();

}


so as you can see I am using e through m as it was a Manager object but clearly e is a CEO object.

so now I call m->printData(), but how is this call even invoked? e has no member function nameed print data as it's a CEO not a Manager object.

the function is indeed called and prints a garbage value, I understand why a garbage value is printed but how is the actual function called itself when clearly the object in memory is a CEO object, the CEO object in memory has no member function printData() so how is this function even executed?

thanks

Last edited on
Basically, you told the compiler that m is pointing at a manager object, and it believes you, and it treats that object as if it's a Manager object, and these objects are so simple that it didn't crash. This is very dangerous and a very bad idea, but C++ trusts you to know what you're doing when it comes to memory.




You have created a pointer to a Manager, called m.

You have pointed that pointer at an object. You've pointed it at an object that happens to be of type CEO, but this is C++ and if you want to make a pointer point at something, you can do that. I don't remember the rules for exactly when you can and cannot static_cast a pointer to a different kind of pointer (I never do it; static_cast of a pointer generally means something has gone very wrong in the design); looks like this case is permitted.

So now you've got a pointer-to-Manager, pointing at an object of type CEO.

Then, you call a function through that pointer. The function you call is effectively this function:

Manager::printData( Manager* this) It's "call this function, named printData, on THAT object over there" The compiler will check that the object is of a class that has such a function, but in this case, everythign's fine - it does, because the object is a Manager object. It must be, right? That's what you told it the object was.

This is how C++ class functions work, in practice. So what happens next?

cout << "print data from manager" << data << endl;

What is data? It's a value inside the object. A piece of memory. So what gets output? Whatever happens to be in that memory.

Here, run this code:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

using namespace std;

class Employee{

 public:
    virtual void f(){}

};

class Manager : public Employee{

   public:
       int data;
       int dataTwo;

       void printData(){
           cout << "print data from manager" << data << endl;
       }

};

class CEO : public Employee{

  public:
      int moreData;
      double d;

  CEO() : moreData(7){}

};


int main()
{

    Employee* e = new CEO;
    Manager* m = static_cast<Manager*>(e);

    

    cout << "Address of CEO object: " << e << '\n';
    cout << "Location Manager pointer is pointing at: " << m << '\n';
    m->printData();

   
}


See what happens with this code? You (probably) see the number 7 output. You're calling the function printData() on what you have told the compiler is a Manager object, but it isn't really, is it?

the CEO object in memory has no member function printData() so how is this function even executed?


NO object in memory has a member function printData() - there is ONE function printData somewhere, and that same function is used every time it's called. You told the compiler to execute the function on an object that you said was a Manager object. The compiler believed you.
Last edited on
When you think of it like C, and every function is just a static function that you have to manually put the *this pointer in every time, you are just calling the function and the offset location of where data is, is substituted with CEO's moreData.

Usually you need to do a reinterpret cast do make fragile code like this work, but I imagine it has to do with the fact both classes share the same base class.
oh ok so

Manager::printData( Manager* this)


this in our case will be m, this is allowed because the compiler believes m is pointing to a manager object so it will accept m as Manager* this?

also I may be mixing up how functions are declared.

NO object in memory has a member function printData() - there is ONE function printData somewhere, and that same function is used every time it's called. You told the compiler to execute the function on an object that you said was a Manager object. The compiler believed you.


When you think of it like C, and every function is just a static function that you have to manually put the *this pointer in every time, you are just calling the function and the offset location of where data is, is substituted with CEO's moreData.


so you guys are saying that an object in memory does not store it's functions (member functions) in memory, instead these functions are static in another part of memory? or in other words there only exists one function in memory of each respective function no matter how many instances there is of a class in memory?

this is also kind of how and why function pointers work?


thanks guys :)

Last edited on
here only exists one function in memory of each respective function no matter how many instances there is of a class in memory?


That's the basic fact of it.

It's worth saying that all this is interesting and worth knowing and that if you ever deliberately program like this, your colleagues will murder you and rightly so.
very true :)
Topic archived. No new replies allowed.