Peter Lee
Peter Lee

Reputation: 13809

Confused with C++ Inheritance

I'm so confused with the output of the following code:

#include <iostream>

using namespace std;

class Parent
{
public:
    Parent() : x(2) { }
    virtual ~Parent() { }

    void NonVirtual() { cout << "Parent::NonVirtual() x = " << x << endl; }

private:
    int x;
};

class Child : public Parent
{
public:
    Child() : x(1) { }
    virtual ~Child() { }

    void NonVirtual() { cout << "Child::NonVirtual() x = " << x << endl; }

private:
    int x;
};

int main()
{
    Child c;
    Parent* p = &c;

    c.NonVirtual();  // Output: Child::NonVirtual() x = 1
    p->NonVirtual(); // Output: Parent::NonVirtual() x = 2
    // Question: are there two x'es in the Child object c?
    //           where is x = 2 from (we have not defined any Parent object)?

    cout << sizeof(c) << endl;
    cout << sizeof(*p) << endl;

    return 0;
}

Upvotes: 4

Views: 1206

Answers (2)

nsivakr
nsivakr

Reputation: 1595

There is nothing to be confused here. When you invoke a non virtual function, whatever type that has been assigned to, the methods of that type gets invoked.

Here, Parent* p, and the child's address are the same, but the assignment is to the Parent. Thus, all methods that are of non virtual invokes the parent's methods and not the child's one.

Remember, when you use inheritance (especially public one), the child automatically derives all parent's methods and members. Thus, even though, you assign the child's pointer, but assignment takes place to the parent's type.

The only thing you need to make sure is you don't do delete P here as both P and child C, shares the same address.

Upvotes: 0

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95449

The code above illustrates the fact that, in C++, only functions marked virtual are overriden. What you have here is overshadowing, not overriding. In overriding and inheritance, the behavior is based on runtime type which is the normal inheritance behavior you expect, but if you don't declare it virtual, then the behavior is based purely on compile-time type (i.e. declared type). Since p is declared to be of type Parent* it uses the implementation in Parent, while c is declared to be of type Child, and so it uses the version given by type Child. If you declared the method virtual, then in both cases, it would lookup the appropriate version of the function at runtime and invoke the version given in the Child class.

I should also add that you have two different x variables... if you want to share variables between a base class and a derived class, you should mark it "protected" in the base class (although I would argue that it is generally poor design to do so). The x variable that you declare in Child is a different variable from the one in Parent. Remember that x is private in Parent, and so the name x didn't have any meaning in Child until you created a second variable named x in Child.

Upvotes: 5

Related Questions