我注意到在我的代码中由于某种原因没有发生虚拟覆盖。我正在广泛使用多态,因此我可以使用像derived.baseFunc()
这样的构造,其中baseFunc在Derived
中调用虚函数覆盖。
在哪些情况下,vtable结构不会发生,多态行为变得不可靠?
注意:对于一个简单的情况,一切正常,因此不需要发布代码。
更新:vtable看起来很好。似乎有一个命名空间的clusterf ** k可能是问题。此外,将代码复制粘贴到新文件并删除命名空间可以解决问题。
答案 0 :(得分:7)
由于没有代码,很难肯定地说出来,但这里有一些疯狂的猜测/选项
您实际上没有覆盖该方法。你可能认为你有,但事实上你可能会弄错。例如:
struct Base{
virtual int f(int);
virtual int g() const;
virtual ~Base();
};
struct Derived: Base{
int f(); //doesn't override Base::f
int g(); //doesn't override Base::g
};
从构造函数中调用虚函数不会像您期望的那样工作。例如,
struct Base
{
Base()
{
f();
}
virtual void f() {}
virtual ~Base();
};
struct Derived : Base
{
void f() { cout << "Derived"; }
};
Derived d; //Derived will NOT be printed
某些构造不会调用虚拟分派,例如合格的funcion调用:ClassName::MethodName()
在任何情况下,对于任何多态类,vtable总是存在,所以不要责怪编译器:)
答案 1 :(得分:5)
任何符合标准的编译器都将具有适当的vtable和多态性。在正确编写的代码中,覆盖总会发生。
您需要检查代码中的一些常见编码错误。例如:
由于您说derived.baseFunc()
种情况没有覆盖,请检查derived
是对象还是引用。请记住,运行时多态性仅适用于指针&amp;参考
功能签名对于成功覆盖非常重要:
struct Base
{
virtual void foo (int) {}
};
struct Derived : Base
{
virtual void foo () {} // oops, this `foo` is different than `Base::foo`
};
答案 2 :(得分:0)
如果您的代码是正确的,那么虚函数将按预期工作。作为优化,编译器可以将虚函数调用转换为正常函数调用,如果它是关于静态类型的100%确定,则动态类型对于此调用的范围具有“静态”性质,即在编译时确定调用发生在无法更改的编译时已知类型上,因此该函数不可能只是一个具体函数。
大多数情况下,情况就是这样,因为您使用强制转换或范围解析明确告诉编译器。无论如何,它仍然按预期工作,没有可观察到的差异(不同的机器代码,确保更有效,但行为相同)。
这与vtable的产生无关。无论如何都会生成vtable(如果编译器使用vtable来实现虚拟继承,大部分/全部都可以,但严格来说 <)>。
如果它没有按预期工作,你可能hide虚拟功能(无意中)。