重载、重写和隐藏
重载同名不同参数,重写派生类改写虚函数,隐藏基类同名函数被遮蔽。
重载、重写和隐藏
重载、重写和隐藏
这是 C++ 面试和实际开发中常见但容易混淆的三个概念:函数重载(Overload)、函数重写(Override)、函数隐藏(Hide)。
总览对比表
特性 | 重载 Overload | 重写 Override | 隐藏 Hiding |
---|---|---|---|
发生位置 | 同一个类中 | 派生类中 | 派生类中 |
条件 | 函数名相同,参数列表不同 | 函数名相同,参数完全相同,且为虚函数 | 函数名相同,但参数列表不同或非虚函数 |
是否继承相关 | 无关 | 有关(父类必须有虚函数) | 有关 |
多态支持 | 否 | 支持运行时多态 | 否(可能造成误用) |
重载(Overload)
概念:
在同一个作用域中,函数名相同,但参数类型或个数不同,编译器根据参数匹配调用对应函数。
示例:
1
2
3
4
5
class Print {
public:
void show(int x) { cout << "int: " << x << endl; }
void show(double x) { cout << "double: " << x << endl; }
};
特点:
- 发生在编译期(静态绑定)
- 无需继承关系
- 返回值类型不同不能构成重载(参数必须不同)
重写(Override)
概念:
在派生类中重新定义基类的 virtual
函数,且参数列表、函数名、返回值都必须一致,用于实现运行时多态。
示例:
1
2
3
4
5
6
7
8
9
class Base {
public:
virtual void speak() { cout << "Base speaks\n"; }
};
class Derived : public Base {
public:
void speak() override { cout << "Derived speaks\n"; }
};
特点:
- 基类函数必须是
virtual
override
关键字可加可不加,建议使用- 实现 动态多态(运行时绑定)
隐藏(Name Hiding)
概念:
在派生类中定义了一个与基类同名但参数不同的函数,会隐藏掉基类的所有同名函数,包括重载版本。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Base {
public:
void show(int x) { cout << "Base int\n"; }
void show(double x) { cout << "Base double\n"; }
};
class Derived : public Base {
public:
void show(string x) { cout << "Derived string\n"; }
};
int main() {
Derived d;
d.show("hello"); // OK
d.show(10); // ❌ 编译错误,Base::show 被隐藏
}
如何解决?
使用 using Base::show;
引入基类版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Base {
public:
void show(int x) { cout << "Base int\n"; }
void show(double x) { cout << "Base double\n"; }
};
class Derived : public Base {
public:
using Base::show; // ✅ 解除隐藏
void show(string x) { cout << "Derived string\n"; }
};
int main() {
Derived d;
d.show("hello"); // 输出: Derived string
d.show(10); // 输出: Base int ✅ 正常
d.show(3.14); // 输出: Base double ✅ 正常
}
情况 | 建议操作 |
---|---|
函数设计用于多态 | 加上 virtual 和 override |
子类增加同名函数(非重写) | 用 using Base::func 避免隐藏 |
编写重写函数时 | 一定写 override 避免错误 |
不希望某虚函数被子类重写 | 用 final 关键字 |
本文由作者按照 CC BY 4.0 进行授权