Questions about static_cast

I wrote a piece of code, but I am confused by its output:

#include <iostream> using namespace std; class B{ public: virtual void foo() {cout << "B::foo" << endl;} }; class D:public B{ public: virtual void foo() {cout << "D::foo" << endl;} void disp() {cout << "D::disp" << endl;} }; void func(B *pb){ D *pd1 = static_cast<D*>(pb); pd1->foo(); pd1->disp(); } int main(int argc, char *argv[]) { B* pb = new B(); func(pb); return 0; } 

Output:

 B::foo D::disp 

But as far as I know, pb points to type B. And is there a function in it with the name disp() ? So why could he access the disp() function in class D?

+4
source share
5 answers

Since disp() does not have access to any member of the class, it is basically the same as if it were declared in the global namespace, and not in the class, so there are no negative side effects to call it, even if the instance is not corresponds to the class.

What you do is lower the pointer of the base class to the pointer of the derived class, although it was not initialized as such. If disp() tried to access class members that were in D but not in B , you would probably encounter segfaults.

Bottom line: Do not use static_cast for downcasting unless you are sure that the pointer is actually pointing to an instance of the derived class. If you are not sure, you can use dynamic_cast , which fails in case of non-compliance (but there is RTTI overhead, so avoid it if you can).

dynamic_cast will return nullptr if the throw is incorrect or throw a std::bad_cast exception if it refers to links, so you know exactly why this happens, and not possible memory corruption errors.

+4
source

Line:

 D *pd1 = static_cast<D*>(pb); 

Will throw regardless of whether the source pointer is B* or D* . In your case, the result will be a pointer pointing to an object of the wrong type. The disp method will work because it does not use any data element or virtual function of class D In a more complex case, this will lead to unstable behavior or failure.

Your objects are polymorphic. You should use dynamic_cast instead.

+2
source

What is important in this context, I believe that the disp() member function is not hidden inside all objects of type D This is the only function that exists in one place. And any object will try to call disp() , it is determined by the code.

Your static_cast will give what the compiler considers a pointer to D , no matter what pointer you pass to it . And as soon as you have a pointer to D , the compiler will let you call disp() .

In other words, static_cast will not protect you from incorrect pointer input.

+1
source

You did something very bad when you pointed to an object allocated as B to a pointer to a derived class D Here, what the standard says, my emphasis is:

5.2.9 Static Cast

If the rvalue of type "pointer to cv1 B" points to B, which is actually a sub-object of an object of type D, the resulting pointer points to an enclosing object of type D. Otherwise, the result of the cast is undefined .

You static_cast undefined behavior by doing this static_cast . The compiler and runtime can do anything and still be compatible when a program invokes undefined behavior.

+1
source

You need to understand the difference between the different types of C ++ translations .

You are using a static cast here, itโ€™s the same as saying: "I donโ€™t care if it really is or not, just try your hand."

In this case, you want to know if your pointer is actually a derived type that you produce it on. You must use dynamic_cast. This action will only be performed if the pointer is of the correct type. This means that if it fails, it will return a NULL pointer.

The behavior you see is what happens when you do not use the correct order for the assignment, which, although you can try to explain it, you should really avoid it, as it falls into the domain of undefined behavior. In other words, you cannot expect the same side effects for compilers or even different versions of the same compiler. In other words, avoid this.

0
source

All Articles