9_面向对象程序设计之多态

面向对象程序设计之多态

前面课程一直在说, 所有的面向对象的语言, 要解决的一个事情就是不要造相同的轮子.

说得通俗点就是一个代码不要写两遍, 也可以理解成代码的复用

代码复用的两种体现形式 :

  1. 继承

  2. 共用相同的函数

父类的指针或者引用指向子类的对象, 编译器是允许的

但是编译器不让你用子类的指针访问父类的对象

多态

什么是多态 ?

多态就是可以让父类指针有多种形态, 同一个函数代码, 当我传一个父类对象的时候, 它调用的是父类的函数, 当我传一个子类对象的时候, 它调用的是子类的函数

C++ 中是通过虚函数实现多态, 就是在函数前面加上 virtual 关键词

#include "stdafx.h"
#include <stdlib.h>
#include <windows.h>

class Shape
{
    public:
        virtual double area()
        {
            return 0;
        }
};

class Circular:public Shape
{
    private:
        double r;
    public:
        Circular(double r)
        {
            this->r = r;
        }
        double area()   // 如果这两个函数名字不一样了, 那就意味着我下面这个函数是没法共用的
        {
            return PI*r*r;
        }
};

void PrintArea(Shape* s) // 这个函数的参数是父类的一个指针类型
{
/*
当我们想使用这个函数的时候, 你可以创建一个子类的对象, 然后把子类的对象传进来
*/
    s->area();
}

我可能不止有圆形一个子类, 我可能还有三角形正方形等等多个子类, 但是只要我重写了父类里面的 area() 函数, 那就意味着函数 PrintArea(), 所有的子类都可以共用.

这个时候里面有一个恶心的地方, 就是父类里面的这个函数, 除了提供 area() 这么一个函数之外, 它没有别的功能

因为它就是个 shape 形状, 它没法定义长宽高半径这种成员变量, 我只能定义一个获取面积的这样一个函数, 因为任何一个子类都会有一个计算自己面积的功能. 并且父类这个面积函数里面也没法写别的内容, 因为具体的面积怎么去计算, 是由子类来决定的.

所以这个父类它唯一的意义是, 规定了你们必须要实现这个接口, 实现了接口以后才可以使用 PrintArea() 函数

那如果这样的话, 我们可以写得更加简单了 :

class Shape
{
    public:
        virtual double area() = 0;
};

这就是纯虚函数

纯虚函数

  1. 虚函数的目的是提供一个统一的接口函数, 被继承的子类所重载 (重写), 以多态的形式被调用

  2. 如果父类中的函数没有任何实现的意义, 那么可以定义成纯虚函数 : virtual 返回类型 函数名(参数列表) = 0;

  3. 含有纯虚函数的类被称为抽象类 (abstract class), 不能创建对象

  4. 虚函数可以被直接使用, 也可以被子类重写后以多态的形式调用, 而纯虚函数必须在子类中实现该函数才可以使用

如果父类里面有纯虚函数的话, 那么子类是必须要重写这个函数的, 否则编译器报错