1、“overload”翻译过来就是:超载,过载,重载,超出标准负荷;“override”翻译过来是:重置,覆盖,使原来的失去效果。 先来说说重载的含义,在日常生活中我们经常要清洗一些东西,比如洗车、洗衣服。尽管我们说话的时候并没有明确地说用洗车的方式来洗车,或者用洗衣服的方式来洗一件衣服,但是谁也不会用洗衣服的方式来洗一辆车,否则等洗完时车早就散架了。我们并不要那么明确地指出来就心知肚明,这就有重载的意思了。在同一可访问区内被声名的几个具有不同参数列的(参数的类型、个数、顺序不同)同名函数,程序会根据不同的参数列来确定具体调用哪个函数,这种机制叫重载,重载不关心函数的返回值类型。这里, “重载”
2、 的“重”的意思不同于“轻重”的“ 重”,它是“重复”、 “重叠”的意思。例如在同一可访问区内有: double calculate(double); double calculate(double,double); double calculate(double, int); double calculate(int, double); double calculate(int); float calculate(float); float calculate(double); 六个同名函数 calculate, 中任两个均构成重载, 和也能构成重载,而和却不能构成重载,因为和的参数相同。
3、覆盖是指派生类中存在重新定义的函数,其函数名、参数列、返回值类型必须同父类中的相对应被覆盖的函数严格一致,覆盖函数和被覆盖函数只有函数体(花括号中的部分)不同,当派生类对象调用子类中该同名函数时会自动调用子类中的覆盖版本,而不是父类中的被覆盖函数版本,这种机制就叫做覆盖。 下面我们从成员函数的角度来讲述重载和覆盖的区别。 成员函数被重载的特征有: 1) 相同的范围(在同一个类中) ; 2) 函数名字相同; 3) 参数不同; 4) virtual 关键字可有可无。 覆盖的特征有: 1) 不同的范围(分别位于派生类与基类) ; 2) 函数名字相同; 3) 参数相同; 4) 基类函数必须有 virt
4、ual 关键字。 比如,在下面的程序中: #include class Base public: void f(int x) cout f(42); / 运行结果: Base:f(int) 42 pb-f(3.14f); / 运行结果: Base:f(float) 3.14 pb-g(); / 运行结果: Derived:g(void) 函数 Base:f(int)与 Base:f(float)相互重载,而 Base:g(void)被 Derived:g(void)覆盖。 隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下: 1) 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论
5、有无 virtual 关键字,基类的函数将被隐藏(注意别与重载混淆) 。 2) 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有 virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆) 。 比如,在下面的程序中: #include class Base public: virtual void f(float x) cout f(3.14f); /运行结果: Derived:f(float) 3.14 pd-f(3.14f); /运行结果: Derived:f(float) 3.14 / Bad : behavior depends on type of the
6、pointer pb-g(3.14f); /运行结果: Base:g(float) 3.14 pd-g(3.14f); /运行结果: Derived:g(int) 3 / Bad : behavior depends on type of the pointer pb-h(3.14f); /运行结果: Base:h(float) 3.14 pd-h(3.14f); /运行结果: Derived:h(float) 3.14 请大家注意,f()函数属于覆盖,而 g()与 h()属于隐藏。从上面的运行结果,我们可以注意到在覆盖中,用基类指针和派生类指针调用函数 f()时,系统都是执行的派生类函数 f(),而非基类的 f(),这样实际上就是完成的“接口” 功能。而在隐藏方式中,用基类指针和派生类指针调用函数 f()时,系统会进行区分,基类指针调用时,系统执行基类的 f(),而派生类指针调用时,系统“隐藏”了基类的 f(),执行派生类的 f(),这也就是“隐藏”的由来。先说区别: 重载: 函数名不变,返回类型可变,参数类型可变,参数个数可变。 覆盖: 全都不可变。 继承后,子与父都想用同一个函数名时,可用重载。 继承后,父函数的内容想重新更改,使用覆盖即重写。