void *转换为基类并调用虚函数

时间:2014-03-04 02:42:38

标签: c++ void-pointers

我有一些这样的代码:

#include <iostream>

using namespace std;
//base class
class Base
{
    public:
        Base(){}

        virtual void f()
        {
            cout<<"father.f()"<<endl;
        }
        virtual ~Base(){}
};
//a empty class
class Base1
{
    public:
        Base1(){}
        virtual ~Base1()
        {
            cout<<"~base1"<<endl;
        }
};
//the child class of the base class
class Child :public Base
{
    public:
        Child(){}
        virtual ~Child(){}
};
//the grandchild class of the base class,and child class of the base1 class
class Grand :public Base1,public Child
{
    public:
        Grand(){}
        virtual ~Grand(){}
        //overwrite base's f()
        void f()
        {
            cout<<"grand.f"<<endl;
        }
};
int main()
{
    void *v = new Grand();
    Base *b = (Base*)(v);
    //i think it print "father.f()",but it print"~base1"
    b->f();
    return 0;
}

我在code :: blocks(version13.12)中运行这些代码,但它打印“~base1”,我不知道它为什么不打印“father.f()”。我认为v点到宏的虚拟表的地址,所以当我将v转换为base并调用f函数时,b调用虚拟表中的第一个虚函数。

我不知道我是对还是错,你能不能告诉我。谢谢所有人!

1 个答案:

答案 0 :(得分:0)

因为有多重继承,所以不能在不经过子类的情况下直接转换为上层类。这是因为void*不包含有关构成最终Grand*实例的各种类的内存布局的任何信息。

要解决此问题,您确实需要将其强制转换为运行时类型:

Base *b = (Base*)(Grand*)v;
b->f();

考虑布局可能在不同位置Base的事实。想想另一个

class Grand2 : public Something, public Else, public Base1, public Child {
  ..
}

现在,Base位于Grand2结构中的哪个位置?与Grand相比处于不同的位置。编译器如何才能知道从指向非指定类(可能是GrandGrand2)的指针开始的正确偏移?