C++三大特性之多态

原文地址:https://qunxinghu.github.io/2016/09/08/C++%20%E4%B8%89%E5%A4%A7%E7%89%B9%E6%80%A7%E4%B9%8B%E5%A4%9A%E6%80%81/ios

概念

多态(Polymorphisn)

多态性是容许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值以后,父对象就能够根据当前赋值给它的子对象的特性以不一样的方式运做。简单的说:容许将子类类型的指针赋值给父类类型的指针(一个接口,多种方法)。
C++ 支持两种多态性:编译时多态性,运行时多态性。
a、编译时多态性(静态多态):经过重载函数实现
b、运行时多态性(动态多态):经过虚函数实现。git

多态的做用

那么多态的做用是什么呢,封装可使得代码模块化,继承能够扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的到底是那个类的对象,函数都可以经过同一个接口调用到适应各自对象的实现方法。github

多态的用法

运行时多态:ide

最多见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,能够根据指向的子类的不一样而实现不一样的方法。若是没有使用虚函数的话,则利用基类指针调用相应的函数的时候,将总被限制在基类函数自己,而没法调用到子类中被重写过的函数。由于没有多态性,函数调用的地址将是必定的,而固定的地址将始终调用到同一个函数,这就没法实现一个接口,多种方法的目的了。模块化

非运行时多态:函数

经过函数重载实现spa

简而言之:指针

  1. 有virtual才可能发生动态多态现象
  2. (无virtual)调用就按原类型调用

使人迷惑的隐藏规则

隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则以下:code

  • 若是派生类的函数与基类的函数同名,可是参数不一样。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆,重载是在同一个类中,而隐藏涉及派生类与基类)。
  • 若是派生类的函数与基类的函数同名,而且参数也相同,可是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆,覆盖有virtual关键字)。

C++虚函数

虚函数: 就是容许被其子类从新定义的成员函数,子类从新定义父类虚函数的作法,可实现成员函数的动态覆盖(Override)。对象

纯虚函数: 是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义本身的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”

virtual void funtion()=0

抽象类: 包含纯虚函数的类称为抽象类。因为抽象类包含了没有定义的纯虚函数,因此不能进行实例化。

纯虚函数的做用:

  1. 为了方便使用多态特性,咱们经常须要在基类中定义虚拟函数。
  2. 在不少状况下,基类自己生成对象是不合情理的。例如,动物做为一个基类能够派生出老虎、孔雀等子类,但动物自己生成对象明显不合常理。
    为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。

示例代码:

#include<iostream>
using namespace std;

//基类对象
class Base
{
public:
    //有virtual关键字,运行时多态
    virtual void f(float x)
    {
        cout<<"Base::f(float)"<< x <<endl;
    }
    //无viratul关键字,不会发生运行时多态
    void g(float x)
    {
        cout<<"Base::g(float)"<< x <<endl;
    }
    void h(float x)
    {
        cout<<"Base::h(float)"<< x <<endl;
    }
};
class Derived : public Base
{
public:
    virtual void f(float x)
    {
        cout<<"Derived::f(float)"<< x <<endl;   //多态、覆盖
    }
    //子类与父类的函数同名,无virtual关键字,则为隐藏
    void g(int x)
    {
        cout<<"Derived::g(int)"<< x <<endl;     //隐藏
    }
    void h(float x)
    {
        cout<<"Derived::h(float)"<< x <<endl;   //隐藏
    }
};
int main(void)
{
    Derived d;  //子类
    Base *pb = &d;  //基类指针指向子类
    Derived *pd = &d;   //子类指针指向本身
    // Good : behavior depends solely on type of the object
    pb->f(3.14f);   // Derived::f(float) 3.14   调用子类,多态
    pd->f(3.14f);   // Derived::f(float) 3.14   调用子类

    // Bad : behavior depends on type of the 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   无多态,调用本身的
    return 0;
}
相关文章
相关标签/搜索