How does a static_cast work?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • abcxxx123
    New Member
    • Jul 2010
    • 2

    How does a static_cast work?

    When I static_cast a Derived object to a base object and call a print function with a base pointer, I still am getting the print function from Derived. I am a little confused as I was expecting base class print function.

    Code:
    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    class Base
    {
            int i;
    public:
            Base()
            {
                    std::cout<<"Base Constructor"<<endl;
            }
            Base(const Base &)
            {
                    std::cout<<"Base Copy Constructor"<<endl;
            }
            virtual ~Base()
            {
                    std::cout<<"Base Destructor"<<endl;
            }
            virtual void print()
            {
                    std::cout<<"Its Base"<<endl;
            }
            virtual void print_s ()
            {
                 std::cout << "Its Base print_2" << endl;
            }
    };
    
    class Derived : public Base
    {
    public:
            Derived()
            {
                    std::cout<<"Derived Constructor"<<endl;
            }
            Derived(const Derived &)
            {
                    std::cout<<"Derived Copy Constructor"<<endl;
            }        
            virtual ~Derived()
            {
                    std::cout<<"Derived Destructor"<<endl;
            }
            void print()
            {
                    std::cout<<"Its Derived"<<endl;
            }
            void print_s ()
            {
                 std::cout << "Its Derived print_2" << endl;
            }        
    };
    
    int main(int argc, char *argv[])
    {
       
            Base* b = new Derived;
            Base* bptr = new Derived;
    
    
            (*bptr) = static_cast<Base>(*b);
            bptr->print();
    
    
            return 0;
    }
    Last edited by Banfa; Jul 6 '10, 12:57 PM. Reason: Added [code]...[/code] tags round the code, please use them in future
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    While you did down cast a derived object into a base object you then copied it into derived object before calling print on that object.

    The object you copied it into was not changed, in fact can not change. So when you called print it called the derived print.

    To call base::print from a derived object pointer you can use
    bptr->Base::print( );

    To verify that static_cast does properly down cast to a base object you can try
    static_cast<Bas e>(*b).print() ;

    Comment

    • weaknessforcats
      Recognized Expert Expert
      • Mar 2007
      • 9214

      #3
      This is not going to work.

      When you cast a derived object to a base object, the derived portion gets chopped off so all you get is the base part of your derived object.

      This is called slicing and is bad news.

      The object still has the virtual functin table of a derived object. When you call a virtual function that uses data from the drived object you crash because the derived portion of the object was chopped off by the cast.

      You are supposed to use static_cast to cast a pointer to a derived object to a pointer to a base object.

      BTW: You have a memory leak by re-using a pointer to a new Derived without deleting the object first.

      Comment

      • abcxxx123
        New Member
        • Jul 2010
        • 2

        #4
        I agree that this is bad, and there is definitely a memory link. I was just trying to understand what actually happened.

        Are we saying that the vptr of the objects are not changed even though the object is down cast in this case? So, it still points to the derived vtable.

        In that case, it should crash if I accessed any data members of the derived class.

        Comment

        • weaknessforcats
          Recognized Expert Expert
          • Mar 2007
          • 9214

          #5
          A copy of your derived object is made. This copy is a base object. The base object does not have any of the derived objects members. Therefore, it is not a real copy. Instead it is a truncated zombie copy.

          A cast in C++ means a) you are calling some legacy C function with void* arguments or somesuch, or b) your C++ design is screwed up.

          static_cast is intended to copy a pointer to a new type provided the new type is in the hierarchy of the original type. static_cast taskes your word on this. dynamic_cast is the same as static_cast except the new type is verified at run time. That is:

          Code:
          //A is base B is derived
          A y;
          B x;
          A* ptr = static_cast<A*> (&x);
          B* ptr1 = static_cast<B*> (&y);
          will result in ptr and ptr1 having an address whereas:

          Code:
          //A is base B is derived
          A y;
          B x;
          A* ptr = dynamic_cast<A*> (&x);
          B* ptr1 = dynamic_cast<B*> (&y);
          will result in an address for ptr since you can always use a derived object as a base object but ptr1 will be null since you cannot use a base object as a derived object. That is, you cannot downcast in a hierarchy.

          When you do need to downcast, you use the Hollwood Principle and construct a Template Method design pattern in your code.

          Comment

          Working...