kayle
kayle

Reputation: 1146

Why couldnt access the child class when child object reference is assigned to parent object pointer

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?

Upvotes: 1

Views: 1162

Answers (3)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385284

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.

Upvotes: 1

nikolas
nikolas

Reputation: 8975

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.

Upvotes: 1

giorashc
giorashc

Reputation: 13713

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)

Upvotes: 1

Related Questions