5

I'm having trouble on my c++ code ..

class GrandParent {
public:
    GrandParent() 
    { 
        printMe(); 
    }

    virtual void printMe() 
    {
        std::cout << "GrandParent: printme" << std::endl;
    }
}

class Parent : public GrandParent {
public:
    Parent(){}
    virtual void printMe()
    {
         std::cout << "Parent: printMe!" << std::endl;
    }
}

class Child : public Parent {
public:
    Child(){}

    void printMe()
    {
         std::cout << "Child: printMe!" << std::endl;
    }
}

int main()
{
     Child *p = new Child();
     delete p;
}

When I run this code, it prints "GrandParent: printMe". my goal is to print "Child: printMe!". Is there something wrong in overriding printMe?

TobiMcNamobi
  • 4,687
  • 3
  • 33
  • 52
tuty_fruity
  • 523
  • 1
  • 5
  • 18

2 Answers2

5

What you're trying to do isn't possible. At the time of GrandParent's constructor, the only part of the Child object that has been constructed and initialized is the GrandParent part - including the vtable. That is, when you call printMe(), the entry will be GrandParent's. It's only after Child gets constructed that the vtable entry for printMe() gets updated to point to Child::printMe.

Note that it's good that C++ works like this. If Child::printMe had been the one called, then you'd be calling a member function on a not-yet-constructed object. Nothing good can come of that.

Barry
  • 286,269
  • 29
  • 621
  • 977
2

Short answer: That's how C++ works.

When a virtual method is called from the constructor, not the method of the runtime class is used. Instead the method of the compile time class is used.

But there might be an escape using the Curiously Recurring Template Pattern as shown here:

#include <iostream>

template <class T>
class Base
{
protected:
    Base()
    {
        T::printMe();
    }
};

class GrandParent : Base<GrandParent>
{
public:
    GrandParent()
        : Base<GrandParent>()
    {}
    static void printMe()
    {
        std::cout << "GrandParent: printMe!" << std::endl;
    }
};

class Parent : public GrandParent, public Base<Parent>
{
public:
    Parent()
    {}
    static void printMe()
    {
        std::cout << "Parent: printMe!" << std::endl;
    }
};

class Child : public Parent, public Base<Child>
{
public:
    Child()
    {}
    static void printMe()
    {
        std::cout << "Child: printMe!" << std::endl;
    }
};

int main()
{
    GrandParent a;
    std::cout << "..." << std::endl;
    Parent b;
    std::cout << "..." << std::endl;
    Child c;
    std::cout << "..." << std::endl;
}

Output:

GrandParent: printMe!
...
GrandParent: printMe!
Parent: printMe!
...
GrandParent: printMe!
Parent: printMe!
Child: printMe!
...

But yeah, then you have to deal with static methods and multiple inheritence.

Community
  • 1
  • 1
TobiMcNamobi
  • 4,687
  • 3
  • 33
  • 52