重载(overload)

  • 定义

在同一个作用域内,两函数的 函数名相同, 参数不相同(可以是参数类型不同或者是参数个数不同), 那么就说这两个 函数重载

  • 分类

函数重载 和 运算符重载 (本质都一样)

[c-alert type=”error”]注意:返回值类型 不是 函数重载判断依据。[/c-alert]

  • 成员函数重载特征
    • 相同的范围(在同一个类中)
    • 函数名字相同
    • 参数不同
  • 实现重载原理:

C++代码在编译时会根据参数列表对函数进行重命名,例如void Test(int a, int b)会被重命名为_Test_int_int,void Test(int x, double y)会被重命名为_Test_int_double。所以说 函数重载从底层上看它们还是不同的函数

#include<iostream>
using namespace std;
void fun(int a)
{
   cout << "int a" << endl;
}
void fun(double a)
{
   cout << "double a" << endl;; 
}
void fun(int a, int b)
{
   cout << "int a , int b" << endl;;
}
int main()
{
    //函数名相同,参数不同
    fun(1);
    fun(1.1);
    fun(1,2);
}

[c-alert type=”success”]

输出结果:

int a

double a

int a , int b

[/c-alert]

重写(override)

  • 定义

重写也叫做 覆盖。子类 重新定义 父类中 有相同名称和参数虚函数。函数 特征相同 ,但是具体实现不同,主要是在 继承关系 中出现的 。简单说,重写(覆盖)是指派生类函数覆盖基类函数

[c-alert type=”warning”]

注意:

1. 被重写的函数不能是 static 的。必须是 virtual 的。

2. 重写函数必须有 相同的类型,名称和参数列表

3. 重写函数的访问修饰符可以不同。尽管 virtual是private 的,派生类中重写改写为 public, protected 也是可以的

[/c-alert]
  • 特征
    • 不同的范围,分别位于 基类和派生类
    • 函数的 名字相同
    • 参数相同
    • 基类函数必须有 virtual关键字
  • 作用

通过重写,可以实现动态多态,何为动态多态,就是当父类的指针或引用指向被重写的虚函数时,父类的指针或引用指向谁就调用谁的虚函数,而不是说根据类型。在这里,如果去掉父类的虚函数的virtual,则构不成多态,如果去掉子类虚函数的virtual可以构成多态,可以理解为编译器优化。

重定义(redefining)

  • 定义:重定义也叫做 隐藏。子类 重新定义 父类中有 相同名称非虚函数 ( 参数列表可以不同 ) 。也就是说,重定义(隐藏)是指派生类的函数屏蔽了与其同名的基类函数
  • 特征
    • 如果 派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。
    • 如果 派生类的函数与基类的函数同名,并且参数也相同 ,但是基类函数没有 vitual 关键字,此时,基类的函数被隐藏。
#include<iostream>
using namespace std;
class A{
public:
    void f()
    {
        cout << "A" << endl;
    }

public:
    int _x;
};

class B : public A{
public:
    void f(int a)
    {
        cout << "B" << endl;
    }

public:
    int _x;
};

int main()
{
    B b;
    b.f();
}
[c-alert type=”success”]

分析:

很明显,子类隐藏了父类的f函数,这个题目比较迷惑人的是子类的f函数有参数,所以会以为调的是父类的f函数; 但是隐藏只与函数名有关,与参数是没关系的,所以调用的还是子类的f函数,这个程序会提示出错(可能是没有匹配的重载函数之类的错误)。

[/c-alert]