函数的重载、重写、隐藏

 重载:

1、在同一作用域中。

2、函数名相同、参数个数或参数类型不同,返回值可同可不同。

3、重载又称为静态多态,静态绑定,静态决议等。因为要实现重载,所以C++和C的命名方式有所不同。重载主要是为了减轻程序员对函数名的记忆负担,让所有功能相似的函数使用同一名字。

4、任何程序都仅有一个 main 函数的实例。main 函数不能重载。 

5、函数重载和重复申明的区别:

如果两个函数声明的返回类型和形参表完全匹配, 

则将第二个函数声明视为第一

个的重复声明。如果两个函数的形参表完全相同,但返回类型不同,则第二个声明

是错误的。

6、重载与作用域: 

一般的作用域规则同样适用于重载函数名。如果局部地声明一个函数,则该函数

将屏蔽而不是重载在外层作用域中声明的同名函数。由此推论,每一个版本的重

载函数都应在同一个作用域中声明。


隐藏:


1、在不同作用域中,分别在基类和派生类中。

2、隐藏只要求函数名相同就行。

3、在派生类中只要不是重写就是隐藏。

4、隐藏是因为在子类中定义了与基类同名的函数,而将基类的函数隐藏掉,要想访问基类的函数,则必须加作用域限定符。


覆盖(重写):


1、不在同一作用域中,分别在父类和子类中。

2、要求函数名相同,函数参数列表相同,返回值也相同(协变除外)。

3、基类函数必须是虚函数(virtual)。

4、访问修饰符可以不同。

5、覆盖是指父类中的虚函数在子类中被重新定义,所以在子类对象的虚函数表中将由子类中重新定义的函数地址覆盖掉原来父类中虚函数的地址。协变是指虚函数的返回值可以是本类类型的指针或引用。动态多态又称动态绑定、动态决议。



覆盖与隐藏的区别


覆盖是指派生类函数覆盖基类函数,特征是:  
 (1)不同的范围(分别位于派生类与基类);  
(2)函数名字相同;  
(3)参数相同;  
(4)基类函数必须有virtual 关键字。 
  
 “隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:  
 (1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。  
 (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆) 
 隐藏后, 即在子类中看不到父类的函数。 



### C++中函数重载重写隐藏的区别与用法 #### 1. 函数重载 (Overloading) 函数重载指的是在同一作用域内定义多个具有相同名称但参数列表不同的函数。这里的参数列表不同可以体现在以下几个方面: - 参数的数量不同。 - 参数的类型不同。 - 参数的顺序不同。 需要注意的是,函数的返回值类型并不参与区分重载函数[^2]。 以下是函数重载的一个例子: ```cpp #include <iostream> using namespace std; class Example { public: void display(int a) { cout << "Displaying int: " << a << endl; } void display(double a) { cout << "Displaying double: " << a << endl; } }; int main() { Example e; e.display(5); // 调用第一个display e.display(5.5); // 调用第二个display } ``` 运行结果会显示两种类型的变量分别调用了对应的`display`方法[^2]。 --- #### 2. 函数重写 (Override) 函数重写发生在派生类中重新定义基类中的虚函数时。为了实现动态绑定(即运行时多态),基类中的函数必须声明为 `virtual` 关键字修饰。在 C++11 及之后的标准中,可以在派生类中使用 `override` 来显式标记该函数是对基类虚函数重写[^5]。 重写的条件如下: - 基类中的函数必须是虚函数 (`virtual`)。 - 子类中的函数签名(包括返回类型、函数名以及参数列表)应与基类一致(协变返回类型除外)。 - 如果子类未正确匹配基类的虚函数,则不会触发重写行为,而是创建一个新的独立函数[^3]。 下面是一个简单的示例: ```cpp #include <iostream> using namespace std; class Base { public: virtual void show() { cout << "Base::show" << endl; } }; class Derived : public Base { public: void show() override { cout << "Derived::show" << endl; } // 使用override关键字标明这是重写 }; int main() { Base* obj = new Derived(); obj->show(); // 输出 "Derived::show" delete obj; } ``` 在这个例子中,尽管通过基类指针访问了派生类的对象,但由于实现了虚函数机制,最终调用的是派生类版本的方法[^5]。 --- #### 3. 函数隐藏 (Hiding) 当派生类中存在与基类同名的函数时,无论是否有相同的参数列表,都会隐藏掉基类中的所有同名函数。即使它们有不同的参数列表也不会构成重载关系[^4]。 例如,在以下代码片段里,虽然`Derived`类里的`print()`只有一个无参形式,但它仍然掩盖住了来自`Base`类的所有版本的`print()`: ```cpp #include <iostream> using namespace std; class Base { public: void print() { cout << "Base::print()" << endl; } void print(int i) { cout << "Base::print(" << i << ")" << endl; } }; class Derived : public Base { public: void print() { cout << "Derived::print()" << endl; } }; int main(){ Derived d; d.print(); // 调用 Derived 的 print() // d.print(5); // 错误! Base 类的 print(int) 已经被隐藏 Base& b = static_cast<Base&>(d); b.print(); // 正常工作,因为此时按 Base 对象看待 b.print(5); // 同样正常工作 } ``` 要解决这种问题并允许访问被隐藏的成员函数,可以通过作用域解析运算符(`::`)来指定具体想使用的那个版本的函数[^4]: ```cpp d.Base::print(5); // 访问 Base 版本的带参数打印功能 ``` --- ### 总结表格对比 | **特性/类别** | **函数重载** | **函数重写** | **函数隐藏** | |---------------|----------------------------------|---------------------------------------|------------------------------| | 定义位置 | 同一作用域 | 派生类 | 派生类 | | 返回类型影响 | 不影响 | 影响 | 不影响 | | 参数列表要求 | 必须不同 | 必须完全一致 | 可能完全不同 | | 动态绑定支持 | 不涉及 | 支持 | 不支持 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值