关于c++的重载,重写(又称覆盖),重定义(又称隐藏),来做一个小小的总结。
重载最主要是指在同一作用域下的函数名相同,参数不同的函数重载,其强调同一作用域。同名同参,不同返回值不能作为重载,编译器会提示函数重复定义。
重写和重定义主要在体现在继承行为中,子类对父类函数的操作。重写是虚函数的正确用法,指子类对父类的虚函数(带virtual)进行同名同参重写(子类的virtual可写可不写)。重写同时要求函数的返回参数也相同(不相同会报错)或者为协同返回类型(子类重写的函数返回的指针或引用为父类原函数返回的指针或引用的子类)。虚函数的作用是使程序在运行中能够父类指针去调用子类的具体实现,这样在定义接口时,参数直接用父类指针表示就OK,而不用重载多个接口函数来适应不同子类的调用。static方法不能重写,因为静态函数不能被定义为虚函数。同时,如果有一个函数是const函数而一个不是,也不构成重写,因为函数形式已不相同,此时会变成子类对父类的重定义。
在继承行为中,除了虚函数正确使用方式之外,其余皆为重定义,如父类的一个非虚函数fun,子类也有一个非虚函数fun,不管参数是否相同,同名函数皆是重定义。子类重定义父类函数,将会隐藏父类原函数,即在子类中将再也无法调用父类的原函数。
根据作用域,virtual,函数参数,做出下面表格汇总:
以下是测试代码:
#include<iostream>
using namespace std;
class Parent {
public:
int funa() {
cout<<"Parent funa()"<<endl;
}
virtual void funb() {
cout<<"Parent virtual funb()"<<endl;
}
};
class Child: public Parent {
public:
//不带irtual,参数相不相同都算是重定义/隐藏
int funa(int a){
//funa();重定义隐藏了父类函数,无法访问
cout<<"Child funa(int)"<<endl;
}
//虚函数的正确用法,重写/覆盖父类函数
void funb() {
cout<<"Child virtual funb()"<<endl;
}
//带virtual,参数不同的重写
void funb(int) {
cout<<"Child virtual funb(int)"<<endl;
}
//在Child类中对funa(int)构成重载
int funa(int a, int b) {
cout<<"Child funa(int, int)"<<endl;
}
};
int main() {
Child child;
Parent* pParent = new Child;
//child.funa(); //父类函数被隐藏,无法访问,因此报错
pParent->funa(); //"Parent funa()",函数在子类中被重定义/隐藏,只能通过父类指针访问
child.funb(); //"Child virtual funb()",重写/覆盖了父类的函数
pParent->funb();//"Child virtual funb()", 重写,虚函数的正确用法
return 0;
}