C++中派生类调用基类同名非虚函数为何需用using关键字?
问题:派生类无法调用基类重载的operator()的原因
原始代码
#include <iostream> #include <string> class Base { public: void operator()(std::string str) { std::cout << "base str: " << str << std::endl; } virtual void operator()(double d) { std::cout << "base double: "<< d << std::endl; } }; class Derived: public Base { public: void operator()(double d) override { std::cout << "derived double: "<< d << std::endl; } }; int main() { Derived derived; derived(8.0); derived(std::string("hi")); }
编译错误
编译时会报错:no match for call to ‘(Derived) (std::string)’
修改后的可行代码
class Derived: public Base { public: using Base::operator(); void operator()(double d) override { std::cout << "derived double: "<< d << std::endl; } };
原因解释
这是C++的**名称隐藏(name hiding)**规则导致的:
- 当派生类中定义了与基类同名的函数(这里是
operator()),无论参数列表是否一致,基类中所有同名的重载函数都会被派生类的同名函数隐藏,无法直接通过派生类对象调用。 - 派生类里的
void operator()(double d)和基类的operator()属于同名函数,因此基类中接收std::string参数的operator()版本被隐藏。编译器处理derived(std::string("hi"))时,只会在派生类作用域内查找operator(),找不到匹配的版本就会报错。 - 添加
using Base::operator();的作用是将基类中所有名为operator()的函数引入到派生类的作用域中,这样编译器就能找到基类的std::string版本重载,代码即可正常编译运行。
内容的提问来源于stack exchange,提问作者tesla1060
相关产品推荐
相关产品推荐

