C++第八章:多态性

一、多态性概述

        面向对象的多态性可以分为4类:重载多态、强制多态包含多态和参数多态。前面两种统称为专用多态,而后面两种称为通用多态

        包含多态是类族中定义于 不同类中的 同名成员函数 的多态行为,主要是通过虚函数来实现。

多态的实现

        多态从实现的角度来讲可以划分为两类:编译时的多态运行时的多态

        绑定是指计算机程序自身彼此关联的过程,就是把一条消息和一个对象的方法相结合的过程。绑定工作在编译连接阶段完成的情况称为静态绑定;绑定工作在程序运行阶段完成的情况称为动态绑定

二、运算符重载

        运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。

        运算符重载的实质就是函数重载。

运算符重载的规则 

规则如下:

  1.  ++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已经有的运算符。
  2. 重载之后运算符的优先级和结合性都不会改变。
  3. 重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。

        运算符的重载形式有两种,即重载为类的非静态成员函数和重载为非成员函数。运
算符重载为类的成员函数的一般语法形式为:

返回类型 operator运算符(形参表)
{
    函数体
}

        运算符重载为非成员函数的一般语法形式为:

返回类型 operator运算符(形参表)
{
    函数体
}

        返回类型指定了重载运算符的返回值类型,也就是运算结果类型;operator是定义运算符重载函数的关键字;运算符即是要重载的运算符名称,必须是C++中可重载的运算符,比如要重载加法运算符,这里就写“十”;形参表中给出重载运算符所需要的参数和类型。

在C++中,operator 运算符 ---> 函数 

operator +

 C++第八章:多态性_第1张图片

例子:复数相加

#include 

using namespace std;

class Complex
{
public:
    Complex(double r, double i) : real(r), imag(i){}
    void show() const {cout << real << " + " << imag << "i" << endl;}
    Complex operator +(const Complex &other) const
    {
        Complex ret(this->real + other.real, this->imag + other.imag );
        return ret;
    }

private:
    double real, imag;
};

int main()
{
    Complex c1(1,2);
    c1.show();
    Complex c2(2,3);
    c2.show();

    (c1+c2).show();//c1.operator +(c2).show();

    cout << "Hello World!" << endl;
    return 0;
}

        当以非成员函数形式重载运算符时,有时需要访问运算符参数所涉及类的私有成员,这时可以把该函数声明为类的友元函数。

or 友元函数
C++第八章:多态性_第2张图片

C++第八章:多态性_第3张图片

++前 后++ 

效率:++i  >  ++i

 三、虚函数

        在实现c++多态时会用到虚函数。虚函数使用的其核心目的是通过基类访问派生类定义的函数。所谓虚函数就是在基类定义一个未实现的函数名,为了提高程序的可读性,建议后代中虚函数都加上virtual关键字。        

C++第八章:多态性_第4张图片

        虚函数声明 只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候。

        通过指针引用访问虚函数。

例子:选择英雄

#include 
#include 
#include 
using namespace std;

class Hero
{
public:
    virtual void q(){}
};

class HY : public Hero
{
    void q() {cout << "the last sun" << endl;}

};

class ZZ : public Hero
{
    void q() {cout << "i am butterfly" << endl;}

};

class WZJ : public Hero
{
    void q() {cout << "the ice" << endl;}

};

int main()
{
    Hero *p;
    int n = 0;

    cin >> n;
    if (n == 1)
    {
        p = new HY;
    }
    else if (n == 2)
    {
        p = new ZZ;
    }
    else
    {
        p = new WZJ;
    }

    p->q();
    return 0;
}

 C++第八章:多态性_第5张图片

虚表 

C++第八章:多态性_第6张图片

  1. 吸收基类成员----继承
  2. 改造基类成员----覆盖
  3. 添加基类成员
  4. 如果派生类的某函数,在基类没有相应的同名、同形参的函数,该函数被编译时会报错;(如:基类不含fn7 fn8 ,所以调用这两个函数时,编译报错)

C++第八章:多态性_第7张图片

  • 全局函数不能为虚函数; 
  • 静态函数不能为虚函数; 
  • 构造函数不能为虚函数。

虚析构函数 

虚析构函数的声明语法为:
 

virtual ~类名();

        如果一个类的析构函数是虚函数,那么由它派生而来的所有子类的析构函数也是虚函数
        如果有可能通过基类指针调用对象的析构函数(通过delete),就需要让基类的析构函数成为虚函数,否则会产生不确定的后果。

四、纯虚函数与抽象类

纯虚函数的声明格式为:

virtual 函数类型 函数名(参数表)=0;

        实际上,它与一般虚函数成员的原型在书写格式上的不同就在于后面加了“=0”。声明为纯虚函数之后,基类中就可以不再给出函数的实现部分纯虚函数的函数体由派生类给出

部分是纯虚函数就是抽象类

全部都是纯虚函数就是接口类

你可能感兴趣的:(c++,开发语言)