为何声明明确非虚重载虚函数会触发GCC警告?
GCC警告“虚函数被隐藏”的原因解析
你的代码里GCC发出的警告,核心原因是C++的名字查找规则,和参数歧义无关。
先看你的代码:
class A; class B; class Upper { virtual void foo(A& a); }; class Lower : public Upper { void foo(B& b); };
GCC的警告说Upper::foo(A&)被Lower::foo(B&)隐藏了,这是因为C++中,派生类的同名函数会无条件隐藏基类中所有同名的函数——不管参数列表是否不同。这不是重载(重载要求函数处于同一作用域),而是作用域优先级导致的名字隐藏机制。
你以为传入A类实例会调用基类的虚函数,但实际情况是:如果通过Lower类型的对象或指针调用foo(A&),编译器会直接报错——它在Lower的作用域里找到了foo这个名字,但参数不匹配,不会再去基类中查找同名的其他版本。比如:
Lower l; A a; l.foo(a); // 编译错误:找不到匹配的foo(A&),因为Lower的foo(B&)隐藏了基类的版本
编译器发出这个警告,是在提醒你:基类的foo(A&)现在无法通过派生类直接访问了,这大概率和你的预期不符——你原本可能以为两个foo是重载关系,但实际上它们是名字隐藏关系。
如果想让基类的foo在派生类中可见,实现真正的重载,可以在Lower类中添加using声明:
class Lower : public Upper { using Upper::foo; // 将基类的foo引入当前作用域 void foo(B& b); };
这样Lower中就同时存在foo(A&)和foo(B&),传入A或B的实例就能正确匹配对应的函数,编译器也不会再发出警告。
内容的提问来源于stack exchange,提问作者MadScientist
相关产品推荐
相关产品推荐

