IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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++知识库]多态性---虚函数的使用


预习和提问
什么是多态? / 为什么使用多态?
什么是虚函数?
特点,注意?
什么是虚函数表?
纯虚函数和抽象类又是什么?
面试怎么问?

虚函数使用方法

定义
函数返回类型之前使用virtual
只在成员函数的声明中添加,实现中不需要
继承
某个成员函数被声明为虚函数,那么它的子类,以及子类的子类中,所继承的这个成员函数,也自动是虚函数
子类中重写这个虚函数,可以不用在写virtual,但建议写,可读性更好

多态性的解释

(1)体现在具有继承关系的父类和子类之间.子类重新定义(覆盖/重写)父类的成员函数,同时父类和子类中又把这个函数声明为了virtual函数
(2)通过父类的指针,只有到了程序运行时期,根据具体执行到的代码行,才能找到动态绑定到父类指针上的对象(new的是哪个),这个对象是某个子类对象,或者父类对象,系统内部实际上是要查类的虚函数表,根据虚函数表找到函数的入口地址,从而调用父类或者子类的虚函数

理解多态

简单说就是想要实现多态这种效果, 就需要使用虚函数
多态理解为一种效果,形式,而虚函数是实际功能,手段,机制

示例

Main

#include "Son.h"
#include "Father.h"
#include <iostream>

int main()
{
	Father father;
	Son son;

	Father* tmp;

	tmp = &father;
	tmp->play();     //Father---play()

	tmp = &son;
	tmp->play();     //Son---play()

	return 0;
}


Father.h

#pragma once
#include <iostream>

using namespace std;

class Father
{
public:
	virtual void play();

};


Father.cpp

#include "Father.h"

void Father::play()
{
	cout << "Father---play()"<< endl;
}

Son.h

#include "Son.h"


void Son::play()
{

	cout << "Son---play()" << endl;
}

Son.cpp

#pragma once
#include "Father.h"

class Son : public Father
{
public:
	void play();
};

在这里插入图片描述

示例中是写死的一个&father或&son,实际项目中可以根据用户的输入,实现过程中的各种状态来创建对象,根据调用时的指针
根据执行时子类对象进来就调用子类方法,父类对象进来就调用父类方法

总结:形式上,原本调用父类的方法,但是,实际上会调用子类的同名方法

纯虚函数和抽象类

纯虚函数:在基类中声明的虚函数,但是他在基类中没有函数体,或者说没有实现,只有一个声明,但它要求任何派生类都要定义该虚函数自己的实现方法
定义
在该虚函数的函数声明末尾的分号之前加"=0"
示例
Father.cpp

//此示例继续上面代码
class Father
{
public:
	virtual void play2() = 0;  //声明了一个纯虚函数
};

Main.cpp

int main()
{
	//Father father; //报错  不允许使用抽象类类型 "Father" 的对象
	//Father* father = new Father;  //报错,函数体都没有,肯定报错
	//Son* son = new Father;  //同样也是不允许的
	
	//Father* father = new Son;  //必须在子类中定义这个纯虚函数的函数体,否则报错
	//不允许使用抽象类类型 "Son" 的对象:	


	
	return 0;
}

注意
(1)纯虚函数没有函数体,只有函数声明
(2)一旦一个类中有纯虚函数,那就不能生成这个类的对象了(有纯虚函数的类就叫抽象类)
(3)抽象类不能用来生成对象,主要目的是用来统一管理子类对象;换句话说,就是主要用于当做父类来生成子类用的.
(4)子类中必须实现该父类中的纯虚函数,那上面例子说就是,定义了一个play2纯虚函数,必须在子类中定义play2函数体,如下

class Son : public Father
{
public:
	void play2(){};
	//Father* father = new Son    //main.cpp中,这一行就不会报错了
};

父类的析构一般写成虚函数

先说结论:用基类指针new子类的对象,在delete的时候系统不会调用子类的析构函数
示例

//main
	Son son;

在这里插入图片描述

	Son* tmp_son = new Son;
	delete tmp_son;

在这里插入图片描述
到这里,还都是正常释放,看下面示例

	Father* tmp_father = new Son;
	delete tmp_father;  //没有执行子类的析构函数


但是在用父类new子类对象的时候,没有释放"Son"的析构,这段示例可以自己尝试一下.
这肯定就有问题了,只删除了一半
解决
把父类的析构写成虚函数

	virtual ~Father();

在这里插入图片描述
完美解决这个问题,只需要在父类的析构上加了一个virtual ,这个问题就不存在了,子类的析构成功执行
结论
(1)delete tmp_father时,肯定是要调用的父类的析构函数, 但是父类析构函数中,要想调用子类(Son)的析构函数,父类(Father)的析构就要声明成virtual, 也就是说C++中为了获得运行时的多态行为,所调用的成员函数必须得是virtual的.
因为虚函数特性,只有虚函数才能做到用父类指针调用子类的虚函数

(2)父类中的析构函数的虚属性会继承给子类,这意味着子类的析构函数也是虚析构,就算不用virtual修饰也可.虽然名字不同

面试常问

为什么父类的析构一定要写成虚函数?
只有这样,当delete一个指向子类对象的父类指针时,才能保证系统能够依次调用子类的析构函数和父类的析构函数,从而保证对象(父类指针指向子对象)的内存被正确释放

多态的原理?
多态是用虚函数表实现的。
有虚函数的类都会生成一个虚函数表,这个表在编译时生成。

动态绑定与静态绑定?
静态绑定是程序编译时确定程序行为。
动态绑定是程序运行时根据具体的对象确定程序行为。

静态成员可以是虚函数吗?

不能, 因为静态成员函数没有this指针, 因为有this指针才能访问到虚表指针,有虚表指针才能找到虚表从而调用实际应该调用的函数。

构造函数可以是虚函数吗?/虚函数指针在什么时候生成的的?
不能,因为对象中的虚表指针是在构造函数初始化列表阶段才初始化的

对象访问普通函数快还是虚函数更快?
首先如果是普通对象,是一样快的,如果是指针对象或者是引用对象,则调用的普通函数快,因为普通对象在编译时就确定地址了,虚函数构成多态,运行时调用虚函数需要到虚函数表中去查找

注:
对象布局,对象模型,虚函数表,后续会用大篇幅补充…

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-06 15:04:14  更:2021-12-06 15:06:41 
 
开发: 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/24 10:34:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码