C++第八章:多态性

一、多态性概述

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

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

多态的实现

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

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

二、运算符重载

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

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

运算符重载的规则

规则如下:

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

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

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

cpp 复制代码
返回类型 operator运算符(形参表)
{
    函数体
}

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

cpp 复制代码
返回类型 operator运算符(形参表)
{
    函数体
}

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

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

cpp 复制代码
operator +

例子:复数相加

cpp 复制代码
#include <iostream>

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 友元函数

++前 后++

效率:++i > ++i

三、虚函数

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

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

例子:选择英雄

cpp 复制代码
#include <iostream>
#include <cstdlib>
#include <cstring>
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;
}

虚表

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

虚析构函数

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

cpp 复制代码
virtual ~类名();

如果一个类的析构函数是虚函数,那么由它派生而来的所有子类的析构函数也是虚函数。

如果有可能通过基类指针调用对象的析构函数(通过delete),就需要让基类的析构函数成为虚函数,否则会产生不确定的后果。

四、纯虚函数与抽象类

纯虚函数的声明格式为:

cpp 复制代码
virtual 函数类型 函数名(参数表)=0;

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

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

相关推荐
励志成为嵌入式工程师19 分钟前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉1 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer1 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq1 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
记录成长java2 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山2 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
青花瓷2 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
睡觉谁叫~~~2 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
音徽编程2 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
观音山保我别报错2 小时前
C语言扫雷小游戏
c语言·开发语言·算法