C++中的函数重载、覆盖(重写)、隐藏
在 C++ 中,函数隐藏、重载、覆盖(重写)是面向对象编程中容易混淆的概念,它们的核心区别体现在作用范围、函数关系和行为表现上。以下是详细解析:
1. 函数重载(Overload)
定义:在同一作用域内,声明多个函数名相同但参数列表不同的函数(参数类型、个数、顺序不同),编译器会根据实参自动匹配对应的函数。
特点:
必须在同一类内或同一全局 / 命名空间作用域中。
函数名相同,参数列表必须不同(与返回值类型无关)。
不涉及继承关系。
示例:
class A {
public:
void func(int x) { ... } // 重载1:参数为int
void func(double x) { ... } // 重载2:参数为double(与1重载)
// void func(int x) const { ... } // 也是重载(const修饰符不同)
};
2. 函数覆盖(Override,也称 “重写”)
定义:在继承关系中,派生类定义了一个与基类中虚函数完全相同(函数名、参数列表、返回值类型均相同)的函数,从而覆盖基类的虚函数实现。
特点:
必须发生在基类与派生类之间。
基类函数必须用 virtual 声明为虚函数。
派生类函数与基类函数函数名、参数列表、返回值类型完全一致(C++11 允许协变返回类型,即返回值为基类 / 派生类指针 / 引用)。
作用:实现多态,通过基类指针 / 引用调用时,会根据对象实际类型执行派生类的重写函数。
示例:
class Base {
public:
virtual void func() { ... } // 基类虚函数
};
class Derived : public Base {
public:
void func() override { ... } // 重写基类虚函数(override关键字可选,用于检查正确性)
};
3. 函数隐藏(Hide,也称 “名字隐藏”)
定义:在继承关系中,派生类定义的函数与基类函数同名,但因参数列表不同或基类函数非虚函数,导致基类函数被 “隐藏”(派生类中无法直接访问基类的同名函数)。
特点:
发生在基类与派生类之间,函数名相同但不满足覆盖条件。
隐藏的原因:
基类函数非虚函数,派生类同名函数参数不同(无论是否有 virtual)。
基类函数是虚函数,但派生类同名函数参数不同(此时不构成覆盖,而是隐藏)。
访问被隐藏的基类函数需用 基类名::函数名 显式调用。
示例:
class Base {
public:
void func(int x) { ... } // 非虚函数
virtual void show() { ... } // 虚函数
};
class Derived : public Base {
public:
void func(double x) { ... } // 隐藏Base::func(int)(参数不同)
void show(int x) { ... } // 隐藏Base::show()(参数不同,不构成覆盖)
};
// 调用时:
Derived d;
d.func(10); // 调用Derived::func(double)(Base::func(int)被隐藏)
d.Base::func(10); // 显式调用被隐藏的基类函数
d.show(); // 错误!Base::show()被隐藏,需显式调用 d.Base::show()
关键区别总结:
| 概念 | 作用范围 | 函数关系要求 | 核心目的 / 效果 |
|---|---|---|---|
| 重载 | 同一作用域 | 同名,参数不同(与返回值无关) | 简化同名功能的调用(编译期绑定) |
| 覆盖(重写) | 基类与派生类 | 同名、同参数、同返回值,基类为虚函数 | 实现多态(运行期绑定) |
| 隐藏 | 基类与派生类 | 同名,不满足覆盖条件 | 派生类同名函数屏蔽基类函数 |
注意:
override 关键字(C++11)可显式声明派生类函数是重写基类虚函数,编译器会检查是否满足覆盖条件,避免误写为隐藏。
隐藏可能导致意外行为,使用时需注意派生类与基类同名函数的参数匹配。
更多推荐
所有评论(0)