虚函数被隐藏

C++ Virtual function being hidden

本文关键字:隐藏 函数      更新时间:2023-10-16

我遇到一个c++继承问题。

我有一个类层次结构:

class A {
public:
   virtual void onFoo() {}
   virtual void onFoo(int i) {}
};
class B : public A {
public:
    virtual void onFoo(int i) {}
};
class C : public B {
};

int main() {
    C* c = new C();
    c->onFoo(); //Compile error - doesn't exist
}

我的问题是:为什么这不能编译?我的理解是C应该从A继承onFoo函数-事实上,如果你在B中删除onFoo的重新定义,这将编译-但是g++给出了C没有onFoo()函数的错误。

您遇到的问题与c++中名称查找的工作方式有关。特别是,在解析成员时,编译器将查看正在访问该成员的对象的静态类型。如果在该类中找到标识符,则完成查找并(在成员函数的情况下)开始重载解析。如果没有找到标识符,它将在层次结构中逐类爬行,试图每次定位一个级别的标识符

在您的特殊情况下,您有c->onFoo();c类型为C。编译器在C中没有看到任何onFoo的声明,所以它在层次结构中继续向上。当编译器检查B时,它看到在该级别有一个void onFoo(int i)的声明,因此它停止查找,并尝试重载解析。此时,由于参数不一致,重载解析失败。

B级别上存在void onFoo(int)声明的事实具有隐藏任何基类中的其余重载的效果,因为它将停止查找。请注意,这是一个非限定查找的问题,函数仍然存在并适用于对象,但不会被常规查找找到(您仍然可以将其称为c->A::onFoo())。

至于如何处理隐藏,最简单的方法是使用using声明将函数引入作用域:
class B : A {
public:
   using A::onFoo; // All A::onFoo overloads are *considered* here
   void onFoo( int );
};

这里using声明的作用是,当查找B类时,在搜索onFoo标识符时,指示编译器也考虑基类中onFoo的所有重载,从而启用常规查找以查找A::onFoo()

如果您希望基类成员重载派生类成员,您需要使用using:

struct A
{
   virtual void onFoo() {}
   virtual void onFoo(int i) {}
};
struct B : A
{
    using A::onFoo;
    virtual void onFoo(int i) {}
};
struct C : B
{
};

int main()
{
    C* c = new C();
    c->onFoo();
}

这是名称隐藏,基本上只有声明的覆盖存在于B中,其他的重载隐藏在A中

类A和B的方法应该是公共的。而且在每个类声明的末尾都缺少分号。

class A {
public:
   virtual void onFoo() {}
   virtual void onFoo(int i) {}
};
class B : public A {
public:
    virtual void onFoo(int i) {}
};
class C : public B {
};

int main() {
    C* c = new C();
    c->onFoo(); //Compile error - doesn't exist
}

您在A类和b类的方法之前忘记了public:修饰符。因此方法onFoo是私有的,因此在这些类之外的任何地方都不可见。

我猜你错过了在class B中添加这个:

struct B : A
{
    using A::onFoo;
    virtual void onFoo(int i) {}
    void onFoo() {} //This line missing in your code.
};

现在编译了!