1

I have a doubt regarding upcasting. Consider there are two classes, Class Parent and Class child. Child has inherited with parent.

Question:

If i create object pointer for parent, and assigned child object reference. I complied it. the output is "object slicing". Couldn't access the child class specific components

class Parent
{
public:
    int i;

    void school()
    {
        std::cout<<"Parent Class::School()"<<std::endl;
    }
    // virtual goToPlay()
    // {
    //       std::cout<<"Parent Class::goToPlay()"<<std::endl;
    // }    

 };

class Child:public Parent
{
public:
    int j;
    void goToPlay()
    {
        std::cout<<"Child Class::goToPlay()"<<std::endl;
    }
};

int main()
{
    Parent *mParent;
    Child mChild;
    mParent = &mChild;

    mParent->school();
    mParent->goToPlay(); //Error

couldnt access goToPlay() API. If i create a virtual function of goToPlay() in Parent Class, then its is accessible. Can any one tell whats the reason?

kayle
  • 1,126
  • 13
  • 20
  • 3
    please refer to this link you will get all your answers.. http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c#274636 – Hitesh Vaghani Aug 06 '13 at 07:27
  • There is no slicing happening here. – Jonathan Wakely Aug 06 '13 at 10:31
  • @JonathanWakely Child specific components are not copied to mParent pointer object. So child object go sliced. – kayle Aug 06 '13 at 13:58
  • That's because it's a pointer, things don't get "copied to [a] pointer object". The pointer points to the base sub-object, the complete object is still a `Child` though. **There is no slicing happening here.** – Jonathan Wakely Aug 06 '13 at 16:01

3 Answers3

1

Since your pointer type is Parent then only the Parent's api will be accessible since that is what you tell the compiler. (i.e. this pointer points to a Parent object).

In your case a virtual method will make the correct implementation being called. (this is called late binding and it is done during run time via hidden tables in the instance to find the correct address of the method's implementation which in your case is the Child implementation since mParent points to a Child instance)

giorashc
  • 13,691
  • 3
  • 35
  • 71
1

You explicitly declare Parent * mParent, so your object is treated as an instance of Parent. In many use cases, this is exactly what you want - you provide a proper interface for doing something, and the concretely used implementation is of no concern to the end user:

class employee
{
    public:
        virtual double get_salary_in_usd() const = 0;
        virtual ~employee() {}
};

class software_developer : public employee
{
    public:
        double get_salary_in_usd() const { return 100000.; /* i wish */ }
        void be_awesome() {}
        ~software_developer() {}
};

void print_salary(std::shared_ptr<employee> const & emp)
{
    std::cout << "This employee earns $" << emp->get_salary_in_usd()
              << " a month." << '\n';
}

In some cases however, you need to tell at runtime, whether your pointer is a certain child of your base class. This is what dynamic_cast is for:

software_developer me;
employee * me_generalized = &me;

software_developer * me_again = dynamic_cast<software_developer *>(
    me_generalized);
if(me_again != nullptr)
{
    me_again->be_awesome();
}

Note that dynamic_cast can return nullptr if the pointer could not be casted. Also note that this happens with RTTI during runtime, and slows down your application. Avoid using this whenever possible.

nikolas
  • 8,707
  • 9
  • 50
  • 70
  • So again we need to do downcasting to avoid object slicing? – kayle Aug 06 '13 at 09:21
  • @kayle This is always true when dealing with polymorphism. The trick is to design your application that it is not, or as little as possible, reliant on downcasting. – nikolas Aug 06 '13 at 09:23
1

In order to use Child::goToPlay() through a pointer-to-Parent, Parent would have to declare its own function goToPlay(), and this function would have to be marked virtual. Your Child class then overrides that function.

Then, when you call goToPlay() on the Parent pointer, the Child function is magically invoked instead.

However, you can't just do this for arbitrary functions that doesn't even exist in Parent.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055