hit*_*shg 6 c++ virtual overriding name-hiding
考虑一下代码:
class Base {
public:
virtual void gogo(int a){
printf(" Base :: gogo (int) \n");
};
virtual void gogo(int* a){
printf(" Base :: gogo (int*) \n");
};
};
class Derived : public Base{
public:
virtual void gogo(int* a){
printf(" Derived :: gogo (int*) \n");
};
};
int main(){
// 1)
Derived * obj = new Derived ;
obj->gogo(7); // this is illegal because of name hiding
// 2)
Base* obj = new Derived ;
obj->gogo(7); // this is legal
}
Run Code Online (Sandbox Code Playgroud)
案例2)
呼叫obj->gogo(7)在运行时解决.
既然obj->gogo(7)合法.它似乎意味着Derived包含ptr的
vtable virtual void gogo(int a)应该被隐藏.
我的困惑是,由于名称隐藏导致案例1)非法,因此2)中的调用如何在运行时解决
a)Derived的vtable是否包含指向gogo(int)的指针.
b)如果a)不为True,虚函数的调用解析是否进入基类的vtable.
您正在混淆虚函数调用和重载解析.
所有派生类都包含包含所有虚函数的vtable,包括基类和任何其他自己的虚函数.这用于在运行时解决调用,就像你的情况2).
在情况1)您在编译时从重载解析获得错误.由于名称隐藏,类Derived只有一个可调用函数.你唯一的选择就是调用那个函数int*.
由于您将第二个声明obj为 a Base*,因此 vtable 为其提供了 的所有方法Base。尽管对于已被 重写的虚拟方法Derived,会调用被重写的版本,但其他方法(或方法重载)仍然是已在 中声明的方法Base。
但是,如果您将指针声明为Derived*,则 vtable 将为它提供 的方法Derived,隐藏 中具有相同名称的方法Base。因此,obj->gogo(7);不会起作用。同样,这也是非法的:
Base* obj = new Derived();
// legal, since obj is a pointer to Base, it contains the gogo(int) method.
obj->gogo(7);
// illegal, it has been cast into a pointer to Derived. gogo(int) is hidden.
(reinterpret_cast<Derived*>(obj))->gogo(7);
Run Code Online (Sandbox Code Playgroud)
这是合法的:
Derived* obj = new Derived ;
obj->Base::gogo(7); // legal.
Run Code Online (Sandbox Code Playgroud)
看这里。