zoukankan      html  css  js  c++  java
  • 虚函数

    --------------siwuxie095

       

       

       

       

       

       

       

       

       

    多态

       

       

    多态 是面向对象的三大特征之一,其它两大特征分别

    是 封装 和 继承

       

       

       

       

       

       

       

    所谓 多态,简单来说,就是当发出一条命令时,不同的对象

    接收到同样的命令后所做出的动作是不同的

       

       

       

       

    而书本上的定义则是:

       

       

       

       

    其实就是在说两个概念:静态多态 动态多态

       

       

       

       

       

    静态多态

       

       

    静态多态,也叫 早绑定

       

       

    看如下实例:

       

    定义一个矩形类:Rect,其中有两个同名成员函数:calcArea(),显然

    二者互为重载(名字相同,参数可辨)

       

       

       

       

    在使用时:

       

    当实例化一个 Rect 的对象后,就可以通过对象分别调用这两个函数,

    计算机在编译时,就会自动调用对应的函数

       

       

       

    程序运行之前,在编译阶段就已经确定下来到底要使用哪个函数,

    可见:很早就已经将函数编译进去了,称这种情况为 早绑定 静态

    多态

       

       

       

       

       

       

       

    动态多态

       

       

    动态多态,也叫 晚绑定

       

       

    看如下实例:

       

    当前要计算面积,于是分别给圆形和矩形下达计算面积的指令,

    作为圆形来说,它有自己计算面积的方法,作为矩形来说,它

    也有自己计算面积的方法

       

       

       

    显然,两种计算面积的方法肯定不同,即 对不同对象下达相同

    指令,却做着不同的操作,称之为 晚绑定 动态多态

       

       

       

    动态多态 是有前提的,它必须以 封装 继承 为基础。在封装中,

    将所有数据封装到类中,在继承中,又将封装着的各个类使其形成

    继承关系

       

       

       

       

    只有以封装和继承为基础,才能谈到动态多态,动态多态

    最起码有两个类,一个子类,一个父类,只有使用三个类

    时,动态多态才表现的更为明显

       

       

    看如下实例:

       

    定义一个形状类:Shape,它有一个计算面积的成员函数:calcArea()

       

       

       

       

    再定义一个圆类:Circle,它公有继承了形状类 Shape,并有自己的

    构造函数和计算面积的函数

       

       

       

       

    圆类计算面积的成员函数在实现时:3.14 * m_dR * m_dR

       

       

       

       

    再定义一个矩形类:Rect,它公有继承了形状类 Shape,并有自己的

    构造函数和计算面积的函数

       

       

       

       

    矩形类计算面积的成员函数在实现时:m_dWidth * m_dHeight

       

       

       

       

    在使用时:

       

    可以使用父类指针指向子类对象,但结果却不尽如人意,因为调用到

    的都是父类的计算面积的函数,即 会打印出两行 calcArea

       

       

       

       

    如果想要实现动态多态,就必须使用 虚函数

       

       

       

       

       

       

    虚函数

       

       

    virtual 修饰成员函数,使其成为 虚函数

       

       

       

       

    如下:在父类中,把想要实现多态的成员函数前加上 virtual 关键字,

    使其成为 虚函数

       

       

       

       

    在定义子类 Circle 时,给计算面积的同名函数也加上 virtual 关键字:

       

       

       

    这里的 virtual 关键字不是必须的,如果不加,系统会自动为你加上,

    而加上了,会在后续的使用中看的更加明显,推荐在子类的定义中也

    加上 virtual 关键字

       

       

       

    同理,定义子类 Rect 时,给计算面积的同名函数也加上 virtual 关键字:

       

       

       

       

    最后,在使用时:

       

    使用父类指针指向子类对象,调用函数时,调用的就是对应子类的

    计算面积函数

       

       

       

       

       

       

       

    程序:

       

    Shape.h:

       

    #ifndef SHAPE_H

    #define SHAPE_H

    //在每一个 .h 文件中都使用了宏定义

    //宏定义是为了避免重复包含所写的

    #include <iostream>

    using namespace std;

       

       

    class Shape

    {

    public:

    Shape();

       

    //这里加上了关键字virtual 会被继承到子类中

    //子类的析构函数即便不写virtual 编译器会自动加上

    //推荐给子类也写上这样看的清楚也是一种好的编程习惯

    virtual ~Shape();

       

    //这里加上了关键字virtual 会被继承到子类中

    //子类的calcArea()即便不写virtual 编译器会自动加上

    //推荐给子类也写上这样看的清楚也是一种好的编程习惯

    virtual double calcArea();

    };

       

    #endif

       

       

       

    Shape.cpp:

       

    #include "Shape.h"

       

    Shape::Shape()

    {

    cout << "Shape()" << endl;

    }

       

    Shape::~Shape()

    {

    cout << "~Shape()" << endl;

    }

       

    double Shape::calcArea()

    {

    cout << "Shape->calcArea()" << endl;

    return 0;

    }

       

       

       

    Rect.h:

       

    #ifndef RECT_H

    #define RECT_H

    #include "Shape.h"

    class Rect :public Shape

    {

    public:

    Rect(double width, double height);

    virtual ~Rect();

    virtual double calcArea();

    protected:

    double m_dWidth;

    double m_dHeight;

    };

       

    #endif

       

       

       

    Rect.cpp:

       

    #include "Rect.h"

       

    Rect::Rect(double width, double height)

    {

    m_dWidth = width;

    m_dHeight = height;

    cout << "Rect()" << endl;

    }

       

    Rect::~Rect()

    {

    cout << "~Rect()" << endl;

    }

       

    double Rect::calcArea()

    {

    cout << "Rect->calcArea()" << endl;

    return m_dWidth*m_dHeight;

    }

       

       

       

    Circle.h:

       

    #ifndef CIRCLE_H

    #define CIRCLE_H

    #include "Shape.h"

    class Circle :public Shape

    {

    public:

    Circle(double r);

    virtual ~Circle();

    virtual double calcArea();

    protected:

    double m_dR;

    };

       

    #endif

       

       

       

    Circle.cpp:

       

    #include "Circle.h"

       

    Circle::Circle(double r)

    {

    m_dR = r;

    cout << "Circle()" << endl;

    }

       

    Circle::~Circle()

    {

    cout << "~Circle()" << endl;

    }

       

    double Circle::calcArea()

    {

    cout << "Circle->calcArea()" << endl;

    return 3.14*m_dR*m_dR;

    }

       

       

       

    main.cpp:

       

    #include<stdlib.h>

    #include "Rect.h"

    #include "Circle.h"

       

    int main(void)

    {

    Shape *shape1 = new Rect(3, 6);

    Shape *shape2 = new Circle(5);

       

    //如果calcArea()不声明为虚函数则会调用父类的calArea()函数

    //输出两个 Shape->calcArea()

    shape1->calcArea();

    shape2->calcArea();

       

    //若想通过delete父类指针来释放子类申请的内存则必须使用虚析构函数

    delete shape1;

    shape1 = NULL;

    delete shape2;

    shape2 = NULL;

    system("pause");

    return 0;

    }

       

    //此即为动态多态(又称晚绑定)动态多态必须建立在封装和继承的基础上

    //至少两个类不同对象收到相同消息(函数)此例即是

    //

    //而静态多态(又称早绑定)如在一个类中的互为重载的函数在对象调用

    //两个函数即相同对象收到不同消息(函数)

       

       

    运行一览:

       

       

       

       

       

       

       

       

       

       

    【made by siwuxie095】

  • 相关阅读:
    services parameters 是如何表现的
    session表有多少条记录?
    php://input 如何用?
    getEditableConfigNames
    UTC + 8 = Beijing Time
    file vs database
    多环境drupal安全install.php
    新建block+cache
    drupal 8 bigpipe lazy_builder
    hook_theme 的重要性
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6805965.html
Copyright © 2011-2022 走看看