OOP特性之多态

1. 什么是多态?

    对于同一种指令,针对不同的对象产生不同的行为

    分为静态多态动态多态:静态多态发生在编译时 --- 函数重载、运算符重载、模板;动态多态发生在运行时 --- 虚函数

2. 虚函数

2.1 虚函数的定义

成员函数名前 + virtual关键字

在派生类中重写虚函数:函数名、参数个数、类型、顺序、返回类型必须和基类中一致

2.2 虚函数的实现: 

         基类定义虚函数时,会在基类存储布局顶部生成一个虚函数指针指向虚函数表。派生类继承虚函数时同样会继承虚函数,并生成派生类自己的虚函数指针和虚标。派生类重写虚函数,覆盖虚表中的函数入口地址。

        NOTICE: 对虚函数的解析发生在运行时。

动态多态被激活的条件

  1. 基类定义虚函数
  2. 派生类重写虚函数
  3. 创建派生类对象
  4. 基类指针指向派生类对象 / 基类引用绑定派生类对象
  5. 基类指针(引用)调用虚函数

Q:动态多态和虚函数等价吗?

A:否,体现动态多态必须有虚函数,但有虚函数不一定能体现动态多态。

2.3 不能被设置为虚函数的函数

① 普通函数(非成员函数)

② 静态成员函数 

  • 发生时机:编译阶段;虚函数在运行阶段
  • 被所有对象共享,无法通过this指针找到虚函数入口地址

③ 内联函数

  • 发生时机不一致
  • 在inline前添加virtual会使其失去内联意义

④ 友元函数

  • 如果函数本身是普通函数,则不能设置
  • 如果函数本身是另一个类的成员函数,则可以设置

⑤ 构造函数

  • 不能被继承,但虚函数可以被继承
  • 发生时机不对
  • 虚函数的调用需要查询虚表,而查询虚表需要虚函数指针,虚函数指针位于内存布局的顶部,如果构造函数没有执行,则无法得到虚函数指针

2.4 虚函数的访问

① 引用访问 --- 动态联编,和指针相同

② 对象访问 --- 静态联编,无法体现动态多态

③ 成员函数访问 --- 动态联编,使用this指针

④ 构造函数和析构函数中访问 --- 静态联编,编译器将虚函数的调用解释为“本类名::虚函数名”,如果在本类中没有实现,则调用基类中的虚函数,但绝不会调用派生类中的虚函数。

静态多态:先期联编 / 静态联编 / 编译时多态

动态多态:晚期联编 / 动态联编 / 运行时多态

3. 特殊的虚函数

3.1 纯虚函数

       virtual type funcName(parameters) = 0    

       在基类中只声明,不定义。

Q:什么是抽象基类?

A:抽象基类有两种形式。一是含有纯虚函数的类;二是将构造函数访问权限设为protected。(抽象基类无法创建对象)

3.2 虚析构函数

① 原因:如果存在基类的指针指向派生类对象,当想通过该指针delete派生类对象时,只会执行基类的析构函数而不会执行派生类析构函数,造成内存泄漏。

② 如果基类的析构函数为虚函数,则派生类中的析构函数自动成为虚函数。

③ 任何一个类都只有一个析构函数且无法重载,因为编译器将所有的析构函数解释为destructor。

4. 重载、隐藏和覆盖

4.1 定义

重载:发生在同一个作用域。函数名相同,返回类型和参数列表不完全相同。
隐藏:发生在基类和派生类。函数名相同,返回类型和参数列表不一定相同。
覆盖:发生在基类和派生类。函数名、返回类型和参数列表完全相同。

4.2 三者的区别

作用域虚函数函数名参数列表返回类型
重载相同不一定相同不同不一定
隐藏不同不一定相同不一定不一定
覆盖不同存在相同相同相同
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值