【C++】多态 ⑤ ( 重载 | 重写 | 重定义 )

2023-10-31 14:17:22 浏览数 (1)

一、重载、重写、重定义概念

1、重载 Overloading

" 重载 " 英文名称 Overloading , 特指 " 函数重载 " ;

" 重载 " 是在 同一个类中 对 函数 或 操作符 进行多次定义 ;

这些 函数或操作符 在 参数类型 或 数量上 有所不同 ; 也就是 参数列表 不同 ;

返回值 并不作为 函数重载 的 判定标准 ;

特别注意 :

  • 函数重载 必须是在 同一个类中进行的 ;
  • 子类无法重载父类的函数 , 如果 子类 函数名和参数列表 与 父类相同 , 那是 重写 Overriding ;
  • 编译器 在 编译阶段 根据调用时 提供的实参 类型 和数量 来决定 具体调用哪个函数 ;

重载的意义 : 提高了 代码的 灵活性 和 复用性 ;

下面同一个类中的 3 个函数就是 函数的重载 :

代码语言:javascript复制
void fun(int a);  
void fun(int a, int b);
void fun(double d); 

上述 3 个函数的 参数列表 中 , 参数的 个数 和 类型 各不相同 , 这是 函数重载 ;

下面的 2 个函数 , 参数列表 和 函数名相同 , 返回值不同 , 不是函数重载 ;

代码语言:javascript复制
void fun(int a);  
int fun(int a);  

函数重载可参考 :

  • 【C 】函数重载 ① ( 函数重载概念 | 函数重载判断标准 - 参数个数 / 类型 / 顺序 | 返回值不是函数重载判定标准 )
  • 【C 】函数重载 ② ( 重载函数调用分析 | 函数重载特点 | 函数重载与默认参数 )

博客 ;

2、重写 Overriding

" 重写 " 英文名称 " Overriding " ;

" 重写 " 是 子类 中定义 与父类中 具有相同名称 和 参数列表 的 虚函数 ;

  • 特别注意 : 重写的函数 , 需要定义为虚函数 , 否则将无法实现多态的特性 ;

" 重写 " 特征 :

  • 重写 是 发生在 父类 与 子类 之间的操作 ;
  • 子类 重写 父类 的 函数 , 子类中 重写父类的 函数 , 必须与 父类的函数 的 函数原型 是相同的 ;
  • 使用 virtual 关键字修饰 父类 和 子类 的函数 , 才叫重写 ; 如果 没有使用 virtual 关键字 , 是 " 重定义 " ;
  • " 多态 " 是 在 函数运行期间 , 根据 实际对象 的类型 , 决定调用哪个函数 ; " 重载 " 在编译阶段决定调用哪个函数 ;

当 子类 对 父类 的函数 实现了 " 重写 " 后 , 在程序运行时 , 根据对象的 实际类型 来调用对应的函数 ;

  • 指针 / 引用 类型 肯定 是 父类类型 , 为该 指针 / 引用 赋值 可能是 父类 , 也可能是 子类 ;
  • 如果 实际类型是父类 , 则调用父类的 函数 ;
  • 如果 实际类型是子类 , 则调用子类的 函数 ;

" 重写 " 使得 子类可以按照自己的需求实现父类的虚函数 , 从而改变继承的行为 ;

重写的意义 : 增强了代码的 扩展性和灵活性 ;

函数重写 , 参考 【C 】多态 ① ( 类型兼容性原则与函数重写 | “ 多态 “ 引入 | 函数重写 ) 博客 ;

重写 代码示例 :

代码语言:javascript复制
class Parent
{  
public:  
    virtual void func() {   
        cout << "父类函数" << endl;   
    }  
};  
  
class Child : public Parent 
{  
public:  
    virtual void func() {   
        cout << "子类函数" << endl;   
    }  
};

3、重定义 Redefinition

如果 子类 重写 父类 的函数 , 分两种情况 :

  • 虚函数重写 : 使用了 virtual 关键字修饰 被重写的函数 , 是 重写 操作 , 会产生 多态 效果 ;
  • 非虚函数重写 : 没有使用 virtual 关键字 , 就是 重定义 ;

子类 中 重定义 父类的函数 , 会导致 父类 的 同名函数被覆盖 , 如果想要调用父类的函数 , 需要使用 父类类名::被重定义的函数() 方式调用 ;

重定义 代码示例 :

代码语言:javascript复制
class Parent
{  
public:  
    void func() {   
        cout << "父类函数" << endl;   
    }  
};  
  
class Child : public Parent 
{  
public:  
    void func() {   
        cout << "子类函数" << endl;   
    }  
};

0 人点赞