一、重载、重写、重定义概念
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;
}
};