重载是编译时多态,依据参数列表在编译期绑定;重写是运行时多态,依据对象实际类型在运行期动态绑定。二者本质区别在于绑定时机与依据:重载看参数匹配,重写看继承关系与方法签名一致性。

重载和重写看起来都是“同名不同行为”,但背后机制完全不同:重载是编译期决定调用哪个函数,属于编译时多态;重写是运行期根据对象真实类型选方法,属于运行时多态。关键不在名字是否相同,而在绑定时机和依据。
重载(Overload):靠参数匹配,编译时就定死
重载发生在同一作用域内,多个函数名相同但参数列表不同(类型、个数、顺序),返回值类型不参与区分。编译器在编译阶段就完成“重载决议”,根据实参类型直接选出唯一匹配的函数版本。
- 不依赖对象类型,只看调用时传入的参数是什么
- 即使把父类引用指向子类对象,调用重载方法仍按引用声明类型选函数
- private / static / final 方法只能重载,不能被重写
- 示例:
print(int)、print(double)、print(string)是三个独立函数,编译器看到print(42)就直接绑到int版本
重写(Override):靠对象实际类型,运行时才决定
重写要求子类中定义一个与父类非私有、非静态、非 final 的实例方法完全同名、同参数、同返回类型(或协变返回)的方法。调用时,JVM 或 C++ 运行时根据对象实际类型(而非引用/指针类型)查虚函数表,动态跳转到对应实现。
- 必须有继承关系,且基类方法需声明为 virtual(C++)或非 final(Java)
- 父类引用指向子类对象时,调用重写方法会执行子类版本
- 字段访问不具有多态性,只有方法调用才触发运行时绑定
- 示例:
Animal* a = new Dog(); a->speak();—— 编译时只知道是Animal*,运行时发现实际是Dog对象,于是调用Dog::speak()
怎么一眼判断是重载还是重写?
看三点:有没有继承关系、方法签名是否完全一致、调用依据是声明类型还是实际类型。
- 同一类里多个同名函数 → 一定是重载
- 子类中方法签名和父类一样,且父类方法可被覆盖 → 很可能是重写(检查 virtual/final 等修饰)
- 调用语句中,左边变量类型和右边 new 出来的类型不一致,还调用了同名方法 → 这是在测试运行时多态,重点看是不是重写生效
- 加了
@Override(Java)或override(C++11)关键字 → 明确表示意图是重写,编译器会校验合法性
常见混淆点提醒
有些情况看似像重写,实为隐藏或重载,容易误判:
- C++ 中子类写了和父类同名但参数不同的函数 → 不是重写,是名字隐藏(除非用
using Base::func;导入) - Java 中子类方法参数列表不同 → 编译器当重载处理,哪怕父类有同名方法
- 静态方法同名 → 只能算“隐藏”,不是重写,也不具备运行时多态
- 构造函数同名 → 不是重载也不是重写,只是构造函数自身的多态形式(本质仍是编译期绑定)

















