派生类重载基类同名函数后,为何无法调用基类的重载版本?
为什么派生类对象无法调用基类的无参
foo()? 嘿,这个问题其实是C++里很经典的**名字隐藏(Name Hiding)**规则在起作用,我来给你掰扯清楚:
先把你的代码贴出来方便对照:
#include <iostream> using namespace std; struct Base { void foo() { cout << "Base foo\n"; } void bar() { cout << "Base bar\n"; } }; struct Derivate : public Base { void foo(int x) { cout << "Derivate foo\n"; } }; // 创建实例 Base a; Derivate b;
你遇到的现象是:基类对象a能正常调用a.foo()和a.bar(),派生类对象b能调用b.bar(),但直接写b.foo()会报错——这本质是C++的作用域查找规则导致的:
- 当你在派生类
Derivate里定义了一个名为foo的函数时,不管它的参数列表和基类的foo是不是一样,基类中所有同名的foo函数都会被隐藏。编译器在处理b.foo()的调用时,只会先在Derivate的作用域里找foo这个名字,找到的是带int参数的版本,发现你调用时没传参数,直接就报错了,根本不会去基类的作用域里找无参的那个foo。 - 而
bar()能正常调用,是因为派生类里没有定义同名的bar,编译器会顺着继承关系往上找,自然就找到基类Base里的bar()了。
如果想让派生类对象能调用基类的无参foo(),有两种简单的解决办法:
在派生类中引入基类的
foo名字
用using Base::foo;把基类的foo引入到派生类的作用域中,这样编译器就能同时看到基类的无参版本和派生类的带参版本,实现重载效果:struct Derivate : public Base { using Base::foo; // 把基类的foo引入派生类作用域 void foo(int x) { cout << "Derivate foo\n"; } };这样
b.foo()会调用基类的无参版本,b.foo(10)会调用派生类的带参版本。调用时显式指定基类作用域
如果你不想修改派生类的定义,也可以在调用时直接告诉编译器去基类里找foo:b.Base::foo(); // 显式调用基类的无参foo
内容的提问来源于stack exchange,提问作者Timo
相关产品推荐
相关产品推荐

