1 概念
函数隐藏指的是派生类中定义的函数会"隐藏"基类中同名的函数,无论参数列表是否相同,基类的同名函数都会被隐藏。
通过派生类对象无法直接访问被隐藏的基类函数,需要使用 对象::基类名::函数 的格式才能访问。
2 原理
C++的名称查找遵循以下规则:
首先在当前类作用域中查找名称
如果找到,停止查找(即使有更好的匹配在基类中)
如果没找到,才会在基类中继续查找
这意味着当派生类定义了某个名称的函数时,编译器会优先选择派生类中的版本,完全忽略基类中的同名函数。
3 场景
3.1 函数隐藏 - 同名同参数
#include <iostream>
class Base {
public:
void print() { // 非虚函数
std::cout << "Base" << std::endl;
}
};
class Derive : public Base {
public:
void print() { // 隐藏了Base::print(),不是重写
std::cout << "Derive" << std::endl;
}
};
int main() {
Derive d;
d.print(); // 输出: "Derive"
d.Base::print(); // 输出: "Base" - 需要显式指定基类
Base* b = &d;
b->print(); // 输出: "Base" - 不是多态行为
return 0;
}3.2 函数隐藏 - 同名不同参
#include <iostream>
class Base {
public:
void print() { // 无参数的print函数
std::cout << "Base" << std::endl;
}
};
class Derive : public Base {
public:
void print(int val) { // 带参数的print函数,隐藏了Base::print()
std::cout << "Derive: " << val << std::endl;
}
};
int main() {
Derive d;
d.print(42); // 正确:调用Derive::print(int)
// d.print(); // 错误:Base::print()被隐藏,无法直接调用
d.Base::print(); // 正确:需要显式指定基类作用域
Base* b = &d;
b->print(); // 正确:调用Base::print()
return 0;
}4 解决
有以下方法:
基类的同名函数使用 virtual 修饰,实现多态;
在派生类中使用 using 声明基类中的同名函数(只适用于“同名不同参”);
在派生类中显示定义一个新的转发函数,封装基类里的同名函数,也就是在在派生类中使用了同名函数重载(只适用于“同名不同参”);
在基类和派生类中使用不同的函数名;
代码示例(使用 using):
class Derived : public Base {
public:
using Base::func; // 引入Base中的所有func函数
void func(double x) { cout << "Derived::func(double)" << endl; }
};
// 现在可以使用:
// Derived d;
// d.func(); // 调用Base::func()
// d.func(42); // 调用Base::func(int)
// d.func(3.14); // 调用Derived::func(double)
评论区