覆盖在祖父母的构造函数中调用的祖父母的虚拟方法

时间:2015-05-27 11:00:09

标签: c++ inheritance

我的c ++代码出现问题..

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;
}

当我运行此代码时,它会打印&#34; GrandParent:printMe&#34;。 我的目标是打印&#34; Child:printMe!&#34;。覆盖printMe有什么问题吗?

2 个答案:

答案 0 :(得分:4)

你想要做的是不可能的。在GrandParent的构造函数时,已构造和初始化的Child对象的唯一部分是GrandParent部分 - 包括vtable。也就是说,当您致电printMe()时,该条目将为GrandParent。只有在构建Child之后,printMe()的vtable条目才会更新为指向Child::printMe

请注意,C ++的工作方式很好。如果Child::printMe 已经被调用的那个,那么你将在一个尚未构造的对象上调用一个成员函数。没有什么好处可以来。

答案 1 :(得分:1)

简短回答:这就是C ++的工作方式。

从构造函数调用虚方法时,不使用运行时类的方法。而是使用编译时类的方法。

但使用Curiously Recurring Template Pattern显示的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;
}

输出:

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

但是,那么你必须处理静态方法多重继承。