C++派生类删除部分函数重载时为何需要using声明引入基类同名函数
问题原理说明
以下是你给出的示例代码:
#include <string> struct A { void f(int) {} void f(double) {} void f(const std::string&) {} }; struct B : public A { using A::f; // 该行是编译通过的必要条件,原因如下 void f(int)=delete; void f(double)=delete; }; int main() { B b; b.f(std::string("toto")); }
这个问题的核心是C++的**名字隐藏(Name Hiding)**规则,具体原因如下:
- 编译器解析成员函数调用时,会从最内层的类作用域向外查找名字,一旦在当前作用域找到目标名字,就会停止向外层(包括基类)作用域查找,后续仅会对当前作用域下找到的所有同名函数做重载决议。注意:查找阶段只匹配函数名,不会校验参数签名。
- 如果删除
using A::f;,编译器在B类作用域查找f时,只会找到你显式定义的两个被删除的重载f(int)、f(double),重载决议阶段没有匹配std::string参数的版本,直接编译报错,根本不会去基类A的作用域查找其他f的重载。 using A::f;的作用是将基类A中所有名为f的重载全部引入到派生类B的作用域中,此时B的作用域下f的重载集合会包含三个版本:从基类引入的f(int)、f(double)、f(const std::string&),以及派生类显式定义的两个被删除的f(int)、f(double)。后续重载决议时:- 传入
std::string参数会匹配到从基类引入的对应版本,编译正常 - 传入
int、double参数会匹配到派生类中被删除的版本,触发编译错误,正好符合你仅保留字符串版本、禁用另外两个重载的需求。
- 传入
内容的提问来源于stack exchange,提问作者SR_
相关产品推荐
相关产品推荐

