栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++仿写多态

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++仿写多态

文章目录
  • 一.多态的原理
    • 1.什么是多态
      • 1.1多态的概念
      • 2.1动态多态和静态多态
    • 2.动态多态实现的具体过程
      • 2.1多态的条件
      • 2.2重写
      • 2.3虚函数
      • 2.4动态多态实现过程
  • 二.仿写多态
    • 1.类成员函数指针
      • 1.1函数调用的两种方式
      • 1.2函数指针的好处
    • 2.代码实现及思路
      • 2.1父类指针指向子类对象
      • 2.2子类对象函数地址覆盖父类对象函数地址
      • 2.3成功仿写动态多态的实现

一.多态的原理 1.什么是多态 1.1多态的概念

在仿写多态之前我们必须先简单了解一下多态是什么?
多态就是相同的行为方式导致了不同的行为结果,即产生了多种形态,即多态

2.1动态多态和静态多态

多态分为静态多态和动态多态

静态多态是编译期的概念,是通过函数重载,模板方法来实现的

动态多态是运行期的概念,是通过继承和虚函数实现的

2.动态多态实现的具体过程 2.1多态的条件

1.必须存在继承关系

2.父类指针指向子类对象,且用这个父类指针调用了虚函数

3.父类中存在虚函数,且继承该父类的子类重写了父类的虚函数

2.2重写

在继承的条件下,子类定义了和父类中某个虚函数一模一样的虚函数(函数名,函数参数列表(参数个数,参数类型),返回值)我们就称之为重写

2.3虚函数

虚函数是实现多态必不可少的条件之一

当一个类中存在虚函数时,定义类的对象的内存空间首地址会多出一块内存(4个字节)在存放虚函数指针(vfptr),这个虚函数指针是一个二级指针(void),这个虚函数指针指向了一个数组,这个数组我们称之为虚函数列表(vftable),虚函数指针是属于对象的,只有在定义对象时才会存在,虚函数指针是属于类的,编译期就存在了,但是必须通过对象才能调

2.4动态多态实现过程

动态多态的具体实现过程
1)父类要有虚函数,父类就有一个虚函数表
2)子类继承父类,子类就有一个虚函数表,
子类重写虚函数,就会覆盖虚函数表里面虚函数地址
3)定义子类对象,子类对象的前4个字节就会有一个虚指针,虚指针指向虚函数表,父类指针指向子类对象
4)父类指针调用虚函数,就会根据子类对象的前四个字节,得到虚指针,进而得到虚函数表的入口地址,通过遍历虚函数表,
找到对应的虚函数并调用,从而完成多态.

二.仿写多态 1.类成员函数指针 1.1函数调用的两种方式

调用函数的两种方式:通过函数名直接调用、通过函数指针间接调用

1.2函数指针的好处

通过函数指针调用的好处:函数指针可以将实现同一功能的多个模块统一起来标识,使系统结构更加清晰,后期更容易维护,提高代码的复用性,降低耦合度

2.代码实现及思路

最终目的:父类指针指向子类对象,子类的函数地址覆盖父类函数地址,当调用父类函数时,实现的是子类的功能

2.1父类指针指向子类对象

父类指针指向子类对象调用的是父类的功能

#include
using namespace std;

class CFather
{
public:
	void show()
	{
		cout << "父类的show方法" << endl;
	}
};
class CSon :public CFather
{
public:
	void show()
	{
		cout << "子类的show方法" << endl;
	}
};

int main()
{
	CFather* pFa = new CSon;//父类指针指向子类对象
	pFa->show();

	return 0;
}

运行结果(请忽略自带的水印):

2.2子类对象函数地址覆盖父类对象函数地址

上面说过调用函数有两种方式,分别是通过函数名直接调用、通过函数指针间接调用
这里我们选择第二种,函数指针调用的方式

void (CFather:: * p_fun)() = (void (CFather::*)()) & CSon::show;//子类函数地址覆盖了父类函数的地址
2.3成功仿写动态多态的实现
#include
using namespace std;

class CFather
{
public:
	void show()
	{
		cout << "父类的show方法" << endl;
	}
};
class CSon :public CFather
{
public:
	void show()
	{
		cout << "子类的show方法" << endl;
	}
};

int main()
{
	CFather* pFa = new CSon;//父类指针指向子类对象
	//pFa->show();
	void (CFather:: * p_fun)() = (void (CFather::*)()) & CSon::show;//子类函数地址覆盖了父类函数的地址
	(pFa->*p_fun)();//通过函数指针的方式调用show函数,
	                //但是父类的show函数地址已经被子类的show函数地址覆盖,从而调用了子类的show函数,从而实现了多态

	return 0;
}

运行结果(请忽略自带的水印):

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1009900.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号