我有一些这样的代码:
#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调用虚拟表中的第一个虚函数。
我不知道我是对还是错,你能不能告诉我。谢谢所有人!
答案 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
相比处于不同的位置。编译器如何才能知道从指向非指定类(可能是Grand
或Grand2
)的指针开始的正确偏移?