1 重载
1.1 定义
重载指的是在同一个作用域内,两函数的函数名可以相同,但是参数不能完全相同,可以是参数类型不同或者是参数个数不同,至于返回值,不影响重载。
1.2 代码解析
//1、函数重载从底层上来说,还是两个不同的函数!
//函数会被编译成_test_int_int
int test(int a,int b){ return 0; }//a
//函数会被编译成_test_int_double
int test(int a,double b){ return 0;}//b
//2、返回值类型不同不可以构成重载
void test(int a,int b){ }//c 会报错,与a函数相同
int main(){
test(1,1);
test(1,2.2);
}
2 重写
2.1 定义
重写指的在继承关系中,子类中定义了一个与父类极其相似的虚函数。
具体怎么相似:函数名必须相同,参数列表必须相同,返回值可以不相同,但是必须是父子关系的指针或引用。
2.2 应用
通过重写,可以实现动态多态,如果去掉父类的虚函数的virtual,则构不成多态,如果去掉子类虚函数的virtual可以构成多态,可以理解为编译器优化。
3 重定义
3.1 定义
重定义也叫隐藏,指的是在继承关系中,子类实现了一个和父类名字一样的函数,(只关注函数名,和参数与返回值无关)这样的话子类的函数就把父类的同名函数隐藏了。
a)如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无virtual,基类的函数被隐藏。
b)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有vitual关键字,此时,基类的函数被隐藏。(如果有virtual就成重写了)
4 重载重定义与重写
下面的代码有点绕,不过理解了,你就通透了
#include <iostream>
using namespace std;
class Base
{
private:
virtual void display() { cout<<"Base display()"<<endl; }
void show(){ cout<<"Base show()"<<endl; }
public:
void exec(){ display(); show(); }
void fun(string s) { cout<<"Base fun(string)"<<endl; }
void fun(int a) { cout<<"Base fun(int)"<<endl; }//overload:两个fun函数在Base类的内部被【重载】
virtual int function(){}
};
class ClassA:public Base
{
public:
void display() { cout<<"ClassA display()"<<endl; }//override:基类中display为虚函数,且参数列表一直,故此处为【重写】
void fun(int a,int b) { cout<<"ClassA fun(int,int)"<<endl; }//redefining:fun函数在Base类中不为虚函数,故此处为重【重定义】
void show() { cout<<"ClassA show()"<<endl; }//redefining:理由同上
//子类会偷偷继承父类的方法哦!
int function(int a){cout<<"ClassA fun(int)"<<endl;}//overload:注意这是重载而不是重写,因为参数列表不同,在编译时ClassA中其实还有个编译器自己偷偷加上的从Base继承来的int function(){};
};
int main(){
ClassA a;
Base *base=&a;
cout<<"0========="<<endl;
base->exec();//display()是ClassA的,因为【重写】 ,show()是Base自己的【理解重写与重定义的不同】
cout<<"1========="<<endl;
a.exec();//结果同上
cout<<"2========="<<endl;
a.show();//show()是ClassA【重定义】的
cout<<"3========="<<endl;
base->fun(1);//fun()是Base自己的,因为直接从对象base调用
cout<<"4========="<<endl;
a.fun(1, 1);//fun()是ClassA重定义的
return 0;
}