【学习笔记】重载和重写的注意事项
特征 | 重载(Overloading) | 重写(Overriding) |
---|---|---|
发生位置 | 同一个类中/父子类之间也可以 | 父子类之间 |
目的 | 扩展功能(增加新的参数组合) | 修改父类行为 |
参数列表 | 必须不同 | 必须相同 |
返回类型 | 可相同或不同(但不能仅依赖返回类型区分) | 必须相同 |
隐藏关系 | 父子类之间,子类隐藏父类同名方法(需 using 声明) | 子类覆盖父类方法 |
关键字 | 无需特殊关键字 | C++: override (override 明确表明派生类中的函数是在重写基类的虚函数) |
重载:
class Calculator {
public:// 方法重载:参数类型不同int add(int a, int b) { return a + b; }double add(double a, double b) { return a + b; }// 方法重载:参数数量不同int add(int a, int b, int c) { return a + b + c; }
};
重写:
class Animal {
public:virtual void makeSound() {std::cout << "Animal makes a sound" << std::endl;}
};class Dog : public Animal {
public:// 重写父类方法void makeSound() override {std::cout << "Dog barks" << std::endl;}
};
注意点(父子的重载):
父子类的重载需要注意一个问题,函数隐藏规则:子类中的 ProcessRequest 会隐藏父类中的所有同名函数,无论参数列表是否相同。
class Base {
public:virtual bool ProcessRequest(int id) { return true; }
};class Derived : public Base {
public:bool ProcessRequest(int id, bool verbose) { return false; } // 参数不同,是重载
};
结果呈现:
int main() {Derived d;// 正确:调用 Derived::ProcessRequest(int, bool)d.ProcessRequest(42, true); // 错误:无法通过 Derived 对象调用 Base::ProcessRequest(int)// d.ProcessRequest(42); // 编译错误!// 正确:通过基类指针调用 Base::ProcessRequest(int)Base* b = &d;b->ProcessRequest(42); // 输出 "true"return 0;
}
● 通过 Derived 对象无法直接调用 ProcessRequest(int),除非使用 using Base::ProcessRequest。
● 通过 Base 指针调用 ProcessRequest(int) 时,实际执行的是 Base 类的方法,而非 Derived 的重载版本。
解决方法:使用using引入父类的方法。
class Derived : public Base {
public:using Base::ProcessRequest; // 引入父类的 ProcessRequest(int)// 子类的重载版本bool ProcessRequest(int id, bool verbose) { return false; }
};
总结:
但是一般重写是在父子类中,重载是在同一个类中。但是需要注意父子重载过程中存在的父类函数隐藏的问题。