这是一个非常基本的例子:
class Base {
public:
virtual void sayHi() const {}
virtual void sayHello() {}
virtual ~Base(){}
};
class Derived : public Base {
public:
virtual void sayHi() {}
virtual void sayHello() const {}
};
int main()
{
Base *b = new Base();
Base *d = new Derived();
return 0;
}
Base的vptr,'b'具有Base类的虚函数。派生类对象'd'然而,在检查时,列出仅基础的虚函数。 这里的问题是不,为什么函数没有被覆盖,所以这里不需要使用override关键字。问题是,为什么特定类的VTable不包含自己的虚函数?在这种情况下,为什么'd'的vtable不包含D :: sayHi和D :: sayHello? 我愿意接受投票,但要勇敢地提及并告诉原因。
编辑: 我知道这里的CONST可能看起来不对,但问题不在于覆盖。
这是在VS2012 Update4中特别尝试的
答案 0 :(得分:1)
这里有不同的函数重载,不会覆盖已定义的虚函数:
virtual void sayHi() const {}
virtual void sayHello() {}
void sayHi() {} // non virtual function with a different signature (no const)
void sayHello() const {} // non virtual function with a different signatuere (const)
如果你想避免这种微妙的错误,请使用关键字override
:如果您认为覆盖基类的虚函数的函数具有不同的签名或者甚至不存在(egtypo) ...)编译器将生成错误。
编辑后修改:
我发现您已更新代码,以使重载的非覆盖函数也是虚拟的。
现在派生函数的vtable包含四个不同的函数。但是,通过基指针,您只能访问基础中定义的虚函数。这就是MSVC调试器仅显示2:
的原因顺便说一下,调试器似乎总是将vtable显示为Base的成员。但是如果你看一下生成的汇编程序,你会在vtable中看到派生类的所有虚函数的错位名称:
答案 1 :(得分:0)
你的Hi函数没有覆盖基类Hi函数,因为它们的const说明符是错误的。 你的Hello函数也是如此,尽管反过来说。 如果您使用C ++ 11或更高版本,则可以使用override关键字来确保不会发生这种情况。
答案 2 :(得分:-1)
已经提到过,当你通过添加const更改函数签名时,你没有覆盖这些函数。
关于您的实际问题: 它将使用来自基类的vtable-pointer指向具有不同条目的自己的vtable。这就是它的工作原理。它“看起来”像基类,但行为“不同”。这就是C ++中的多态行为。
如果每个派生类都会添加自己的vtable,那么很多东西都会在C ++中被破坏。多个vtable指针只是类实例的一部分,它从包含虚函数的多个类或使用虚继承派生。