C++基础-重载/重写/重定义/多态

来源:互联网 发布:0.5是什么意思网络用语 编辑:程序博客网 时间:2024/05/04 20:03

1. 重载(overload)

  • 定义

    • 在一个类内,如果存在若干个同名函数,而且这些函数之间可以用形参个数形参类型区分开来的时候(注意不能靠函数返回类型区分),这几个函数就互为重载函数
  • 注意点

    • 重载发生在类内,不会发生在基类和派生类之间

    • 函数名必须相同,形参个数或类型可以不同

    • 重载函数之间必须依靠形参个数形参类型来进行区分,不能依靠返回类型

      • 如果两个函数同名同参,但返回类型不同,编译器会因为二义性而报错
    • 重载调用:通过类对象调用重载函数时,编译器通过传递的实参个数类型去匹配相应的函数,而不会发生歧义。

      • 体现了重载的作用:可以使用若干个同名函数
    • 虚函数和普通函数之间也可以重载


2. 重写(override,覆盖)

  • 定义

    • 重写也称为覆盖,重写了一个方法以实现不同功能。一般用于子类继承父类时,重写父类中的方法。函数特征相同,具体实现不同。
  • 注意点

    • 重写只能出现在基类和派生类之间,当

      • [1] 基类和派生类之间存在同名函数
      • [2] 返回类型、形参个数和类型完全相同
      • [3] 基类中的该函数必须是virtual(派生类中virtual可有可无)
    • 则派生类中的该函数覆盖掉基类中的该函数,此性质用来实现多态

    • 重写函数的访问修饰符可以不同,即使virtual是private的,派生类中改为public或protected也可以


3. 重定义(redefining,隐藏)

  • 定义

    • 重定义也称为隐藏,派生类对基类成员函数重新定义,即派生类定义了某个函数,该函数与基类中函数同名
  • 注意点

    • 重定义也只能出现在基类和派生类之间,当

      • [1] 基类和派生类之间存在同名函数
      • [2] 无论返回类型、形参个数和类型是否相同
    • 则基类中的同名函数都会被隐藏

      • 如果基类中该函数被重载,则重载函数都会被隐藏,包括虚函数
    • 如果返回类型、形参个数和类型均相同,且基类中为virtual函数,则属于重写

    • 如果要访问基类的该函数,需要在函数名前加上作用域操作符


4. 多态(polymorphism)

  • 定义

    • 多态是面向对象思想的精髓所在,使用多态是为了避免在父类中大量重载而引起代码臃肿和难于维护

    • 关于多态,一种不严谨的说法是:继承是子类使用父类的方法,多态是父类使用子类的方法

  • 多态的分类

    多态可以分为两类:静态多态性 + 动态多态性

    • [1] 静态多态性:又称编译时的多态性,静态多态性是通过函数的重载实现

      • 函数重载运算符重载实现的多态性属于静态多态性,在程序编译时就能决定调用哪个函数
    • [2] 动态多态性:又称运行时的多态性,动态多态性是通过虚函数实现的。

      • 程序运行过程中才动态地确定操作所针对的对象
  • 注意点

    虚函数存在的唯一目的就是为了实现多态,成员函数要以多态的形式来执行,那么必须满足

    • (1) 基类中这些成员函数为虚函数,并必须实现
    • (2) 派生类中这些成员函数必须被重写同名 + 同返回同形参个数和类型 + 基类中为virtual
    • (3) 将派生类的对象赋给基类的指针变量或引用,可用基类的指针或引用调用派生类的方法

    实现多态,上述三个条件必须完全满足,虚函数的特性才能完全发挥出来,也才能实现多态。

  • 不是多态的例子

    • [1] 派生类和基类都是虚函数,派生类中与基类函数同名,形参个数类型与基类中不同,这种情况属于隐藏不会报错

      • 如果形参的个数和类型相同,返回类型也必须相同,否则编译会报错,因为返回类型发生了冲突,隐藏发生错误
    • [2] 基类中是虚函数,派生类中不是虚函数,派生类中与基类函数同名,返回类型形参个数类型与基类不同,这种情况也属于隐藏,如果返回类型、形参个数和类型均相同,这种情况属于重写不会报错

    • [3] 基类中不是虚函数,派生类中是虚函数,或基类派生类中均不是虚函数,派生类中与基类函数同名,这种情况属于隐藏,同样也不会报错


附:实例说明

  • [1] 重载,重写,重定义
#include <iostream>using namespace std;class BasicClass{    private:        int a;    public:        //函数重载实例        void overloadFunc(int k)        {            cout<<"overloadFunc single parameter:"<<k<<endl;        }        void overloadFunc(int k,int t)        {            cout<<"overloadFunc two parameters:"<<" k:"<<k<<" t:"<<t<<endl;        }        virtual void overrideFunc()        {            cout<<"override fun from basic class!"<<endl;        }};class DeriveClass : public BasicClass{    private:    public:        //重定义:隐藏        void overloadFunc(int k)        {            cout<<"redefine overloadFunc from derived Class!"<<endl;        }        //重写        void overrideFunc()        {            cout<<"override from derived class!"<<endl;        }};int main(){    BasicClass a;    DeriveClass b;    //重载调用    cout<<"重载调用"<<endl;    a.overloadFunc(1);    a.overloadFunc(1,2);              //根据形参来区分调用哪个函数    //重写    cout<<endl;    cout<<"重写-该性质可实现多态"<<endl;    b.overrideFunc();    a.overrideFunc();    //隐藏    cout<<endl;    cout<<"重定义/隐藏"<<endl;    a.overloadFunc(1);    b.BasicClass::overloadFunc(1);     //重定义时可以通过作用域操作符访问基类函数    b.overloadFunc(1);    return 0;}
  • [2] 多态
#include <iostream>using namespace std;class A{    public:        virtual void test(int a)        {            cout<<"basic class A: "<<a<<endl;        }};class B: public A{    public:        void test(int b)         //重写-覆盖        {            cout<<"derived class B: "<<b<<endl;        }};class C: public A{    public:        void test(int c)        {            cout<<"derived class C: "<<c<<endl;        }};int main(){    A *a0;          //指针    B b;    C c;    A &a1 = b;      //引用    A &a2 = c;    a0 = &b;    a0->test(2);   //调用类B的test函数    a0 = &c;    a0->test(3);   //调用类C的test函数    a1.test(4);    //调用类B的test函数    a2.test(5);    //调用类C的test函数    return 0;}



Acknowledgements:
http://www.cnblogs.com/DannyShi/p/4593735.html
http://www.cnblogs.com/liangning/p/3968151.html
http://blog.csdn.net/loverooney/article/details/38307523

2017.09.26