| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 多态(虚函数虚函数表纯虚函数虚析构函数抽象类) -> 正文阅读 |
|
[C++知识库]多态(虚函数虚函数表纯虚函数虚析构函数抽象类) |
目录 抽象类(虚基类这个好像是这么叫还是叫纯虚基类来着,记不清了.不过这个不重要) 多态多态嘛,固然就是一个物体有多种形态,在C++中就是一个函数名,有多种功能. 函数重载一般叫静多态,接下来介绍的就是动多态. 静多态在编译阶段决定调用哪个函数 动多态在运行过程中决定调用哪个函数 虚函数C++在编译时需要知道调用函数(非虚函数)的地址,也就是早期绑定. 在基类中使用virtual声明函数,派生类重写该函数时,会告诉编译器不要早期绑定该函数, 动态类型和静态类型只有在基类中有虚函数,派生类重写该函数,并且使用指针或引用指向对象时才会出现动态类型. 满足上述条件后, 派生类B,对象b. A *a = &b;??????? //此时a的动态类型为B(也可以说a的类型就是B) 如果不满足上述条件 A *a = &b;??????? //此时a的静态类型为B,可以说他根本没有动态类型(也可以说a的类型就是A) 在基类的函数前加上virtual(虚函数)关键字,在派生类中重写该函数,运行时根据实际类型调用函数. 在基类某个函数中声明virtual,则派生类中这个函数都是virtual,不需要在显示声明. 静态类型
动态类型(多态实现)此时我们只需要将基类中的show前加上virtual就可以实现多态,也就是动态类型(在运行阶段确定调用哪个函数)
虚函数表(vtable)编译器在基类中发现有虚函数时,会为包含虚函数的类创建一个虚函数表(vtable),该表其实就是一个一维数组,每个数组元素都是一个虚函数地址. 定位虚函数在有虚函数的类中,编译器会另外为每一个对象提供一个虚函数表指针(vptr),这个指针指向了对象所属类的虚函数表.在程序运行时,会根据对象的类型初始化vptr,从而正确的指向虚函数表,调用正确的函数. 上述代码中指针a指向派生类B,则vptr指向派生类B中的vtable,当调用函数show时,会根据函数地址找到派生类B中的show函数. 虚函数初始化时间在构造函数中进行vtable的创建和初始化, 构造派生类对象时,会先构造基类.也就是说会先将vptr指向基类的vtable,之后在构造子类对象的时候子类的vptr才会被初始化指向自己的vtable.(因为顺序执行编译器不知道子类是否存在) 虚函数表的特点vtable可以继承,如果派生类没有重写虚函数,则派生类的vtable仍然使用该地址,只是这个地址的指向是由基类的vtable实现的. 基类中的虚函数地址可以被继承,派生类没有重写会由基类的vtable来实现.如果重写会修改vtable中的地址,由自身的vtable类实现.如果派生类有自己的虚函数,则会在自身的vtable中添加该函数地址. 基类和派生类的vtable中函数地址排列顺序是相同的. 虚函数应用在面向对象程序设计中,类的继承是经常出现的.目的是保留基类的特性,可以大大减少新类的开发时间.可是从基类继承的成员很多时候不能完全满足派生类的需求,利用虚函数可以很好的解决这个问题.(当然了不同的函数名,数据名也可以实现但是会为开发带来重多不便) 纯虚函数纯虚函数只需要声明即可 纯虚函数的基类(虚基类,抽象类)不能创建对象,但是可以创建对象的指针. 纯虚函数和虚函数的区别就在于,虚函数的基类可以创建对象,而纯虚函数的基类不能创建对象. 纯虚函数声明方法virtual 返回值 函数名(参数列表) = 0; 纯虚函数特点只需声明,不用实现,也就是不需要函数体 在形参列表后加 = 0 ,这样可以告诉编译器这是一个虚函数 因为只有声明,纯虚函数不能被调用,只有在派生类中进行重写才可以被使用. 如果基类中是纯虚函数,则派生类继承下去的任然是纯虚函数. 虚析构函数当派生类释放对象时,会先调用派生类析构函数,然后调用基类析构函数. 但是如果对象开辟在堆上,定义一个基类的指针指向派生类.delete这个指针的时候如果不是虚析构函数,只会调用基类的析构函数,不会调用派生类的析构函数.会造成内存泄漏(这个是实际中C++坑最多的地方),但是如果使用虚析构函数就不会出现这种问题.
?当使用虚析构函数时
?虚函数限制非成员函数不能是虚函数 静态成员函数不能是虚函数,静态成员函数是属于类的,不属于对象 内联函数不能是虚函数,编译器会忽略掉inline,使之变成一个虚函数 构造函数不能是虚函数 抽象类(虚基类这个好像是这么叫还是叫纯虚基类来着,记不清了.不过这个不重要)有纯虚函数的基类就是抽象类,他不可以创建对象(实例化对象) 纯虚函数可以被派生类继承,如果派生类没有定义基类中所有的纯虚函数,那么这个派生类也是抽象类,同样不能创建对象. 总结多态是一个接口多种实现,他是面向对象的核心,虚函数(结合虚函数表(vtablehe)和虚函数指针(vptr))可以实现多态(动态绑定(动态类型)). |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 23:48:27- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |