Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - upcasting and downcasting

In my example:

At upcasting, shouldn't the second d.print() call print "base"?

Isn't it "d" derived object upcasted to a base class object?

And at downcasting, what advantages does it have?

Could you explain upcast and downcast in a practical way?

#include <iostream>
using namespace std;

class Base {
public:
    void print() { cout << "base" << endl; }
};

class Derived :public Base{
public:
    void print() { cout << "derived" << endl; }

};

void main()
{
    // Upcasting
    Base *pBase;
    Derived d;
    d.print();
    pBase = &d;
    d.print();

    // Downcasting
    Derived *pDerived;
    Base *b;
    pDerived = (Derived*)b;
}
like image 808
Mihai Avatar asked Jan 30 '16 12:01

Mihai


People also ask

What is Upcasting and downcasting in C?

Upcasting can cause object slicing when a derived class object is passed by value as a base class object, as in foo(Base derived_obj). Downcasting. The opposite process, converting a base-class pointer (reference) to a derived-class pointer (reference) is called downcasting.

What is Upcasting vs downcasting?

Upcasting (Generalization or Widening) is casting to a parent type in simple words casting individual type to one common type is called upcasting while downcasting (specialization or narrowing) is casting to a child type or casting common type to individual type.

What is Upcasting and downcasting in inheritance?

In Upcasting a child object is typecast to a parent object. On the other hand, the reference of the parent class object ends up passing on to the child class when it comes to downcasting.

Which is safe Upcasting or downcasting?

Upcasting is safe casting as compare to downcasting. It allows the public inheritance that implicitly cast the reference from one class to another without an explicit typecast. By default, the upcasting create is-a relationship between the base and derived classes.


2 Answers

Up-casting is implicit in C++, and is used a lot when you deal with virtual dispatching. In other words, you have a pointer to Base from which you can access the common interface of a whole hierarchy of classes, and the selection can be done at runtime. This assumes that your interface functions are marked virtual. Example:

Base* pBase; 
cin >> x; 
if(x == 0) // this is done at runtime, as we don't know x at compile time
    pBase = new Derived1;
else
    pBase = new Derived2;

pBase->draw(); // draw is a virtual member function

It is extremely useful in these situations in which the dispatch is done at runtime. Simply said, upcasting allows one to treat a derived class as a base class (via its common interface).

Down-casting is less useful, and IMO should be avoided whenever one can. In general is a sign of bad design, as one rarely needs to convert a Base object to a derived one. It can be done (and the result checked) via dynamic_cast, like

Base* pBase = new Derived; // OK, the dynamic type of pBase is Derived
Derived* pDerived = dynamic_cast<Derived*>(pBase);
if(pDerived) // always test  
{
    // success
}
else
{
    // fail to down-cast
}

This link provides a quite useful intro to the subject.

like image 181
vsoftco Avatar answered Oct 13 '22 04:10

vsoftco


You need to use virtual methods in order to enable RTTI.

In your case, since you are using C++, you should rely on safer casting mechanisms. So, instead of (Derived*)b, you should be using dynamic_cast<Derived*>(b). This allows you to make sure that you are actually in possession of a pointer to an object to a base class (interface) that was obtained by casting up an object of type Derived. This page provides further explanations.

like image 26
Mihai Todor Avatar answered Oct 13 '22 06:10

Mihai Todor