关于名称隐藏和虚拟功能的困惑

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.

Bo *_*son 5

您正在混淆虚函数调用和重载解析.

所有派生类都包含包含所有虚函数的vtable,包括基类和任何其他自己的虚函数.这用于在运行时解决调用,就像你的情况2).

在情况1)您在编译时从重载解析获得错误.由于名称隐藏,类Derived只有一个可调用函数.你唯一的选择就是调用那个函数int*.


App*_*ker 0

由于您将第二个声明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)

这里