在过程式编程中,咱们经常用到重载,重载的好处显而易见,可让咱们以一个名字去定义某一类操做(对不一样的各类输入),其实在面向对象的类中,重载依然发挥这样的好处。编程
例如以下代码: class base { public: void checknum(int n){cout<<"this is a int num";} void checknum(float n){cout<<"this is a float num";}
}函数
int main() { int i = 5; float j = 5.6; base a; a.checknum(i); a.checknum(j); }this
当上述代码执行完毕,结果最终为 "this is a int num" "this is a float num"指针
注意:重载只在同一个类中产生效果,在同一类中定义某一种操做,属于编译器福利,重载成立的条件: 在同一个类中、函数名字相同、函数参数列表不一样(或是参数类型不一样,或是参数个数不一样)。另外还有注意一点,函数返回类型不构成重载,就好像:code
int check(int a){} float check(int a){}对象
这样的两个函数是不构成重载的。继承
重载说完,咱们说说覆盖的事,在面向对象的过程当中,类(即对某个对象特性的描述)是能够被继承的,就像编译器
卡车是汽车的一种,继承了汽车的特性,然而派生类也有本身的特色,不然咱们还用派生类做甚?(咱们用轿io
车拉货就行了,用卡车干甚?)由于拉货的属性是卡车所独有的,而对于特有的属性,须要有特有的操做,不编译
过这种操做每每只是通用状况的特例,(不管拉货仍是拉人,都只是拉这个操做的特例)因此咱们经常要对派
生类中的操做从新定义以适应当前的状况,这个时候,就用获得覆盖了。
覆盖,顾名思义,是对基类操做的覆盖。
例如以下代码:
class base { public: virtual void check(int i){cout<<"this is base function";} }; class derive :public base { public: void check(int i){cout<<"this is derive function";} };
当使用专门的对象调用本对象的操做时,一切都很天然,但咱们经常喜爱用一个指针指向某一个对象,指针是
万恶之源,尤为是当使用基类指针指向一个派生类对象时,会发生不少事情。
针对上面的代码,使用这样的main函数
int main() { int i = 78; base *a = new derive(); a->check(i); }
当咱们执行完这个main函数,结果为:
this is derive function
假如把类derive中check函数的参数改为float i的话,结果就变成 this is base function 了,由此,我
们能够发现,其实覆盖只是另外一种形式的重载,是类间的重载,对于相同参数列表有效,能够执行不一样的操
做,可是,这仍是不够,咱们须要更加普遍的重载,即使对于不一样参数列表也有效,这就是以下的隐藏。
以代码举例:
class base { public: void check(int i){cout<<"this is base function";} }; class derive :public base { public: void check(float i){cout<<"this is derive function";} }; int main() { int i = 78; base *a = new derive(); a->check(i); }
最终结果为: this is base function
即使在base的check函数前加了virtual,结果仍是同样。
咱们进行最终总结:
重载:
1) 在同一类中;
2) 函数名字相同;
3) 参数不一样;
4) Virtual关键字无关紧要
覆盖:
1) 在不一样范围中(派生类与基类);
2) 函数名字相同;
3) 参数相同;
4) 必须有virtual关键字;
5) 若是函数返回值为引用或指针,能够修改成指向派生类的引用或指针
隐藏:
1) 范围不一样,函数名字相同,参数不一样,Virtual关键字无关紧要;
2) 范围不一样,函数名字相同,参数相同,基类无virtual关键字。
覆盖与隐藏运用中的区别:
覆盖:调用函数取决于指针或引用的对象的类型;
隐藏:调用函数取决于指针或引用的类型。
日常建议使用相应指针指向相应对象,假如必定要用基类指针指向派生类对象的话,请必定注意覆盖和隐藏的
有关事项,不然会有你想象不到的麻烦哦!