多态(c++)


前言

多态是设计模式的基础,是编写软件框架的基础!
面向对象的三大概念(封装、继承、多态)

一、多态的出现是因为面向对象有了新的需求

现在的编译器的做法不是我们期望的

  1. 根据实际的对象类型判断重写函数的调用
  2. 如果父类指针指向是父类对象则调用父类中定义的函数
  3. 如果子类指针指向是子类对象则调用子类中定义的函数

二、面向对象中的多态

根据实际的对象类型来决定函数调用语句的具体调用目标

  				p指向父类对象    就运行父类的print()函数 

p->print();

    			p指向子类对象   就运行子类的print()函数

多态:同样的调用语句有多种不同的表现形态

三、c++给我们提过的多态支持方案

  1. c++中的多态支持
  2. c++通过virtual关键字对多态进行支持
  3. 使用virtual声明的函数被重写后可展现多态性

四、实现多态的三个条件

  1. 要有继承
  2. 要有虚函数重写
  3. 用父类指针(父类引用)指向子类对象

五、多态案例分析

class HeroFighter //父类  这块是一代战机
{
public:
		virtual int power()//要有虚函数
		{
		return  10;
		}
};
class EnemyFighter  //敌机
{
public: 
		virtual int power()
		{
		return 15;
		}
};
class HeroFighter2 : public HeroFighter    //继承  子类继承父类(1)        
{
public:
 		virtual int power()//子类重写父类虚函数(2)
 		{
		return 20}
}//搭建战斗平台
void PlayObj(HeroFighter *hf,EnemyFighter *ef)  //用父类指针指向子类对象(3)
{
	if(hf->power() > ef->power()) //hf->power() 函数调用
	{
	cout<<"英雄机获胜"<<endl;
	}
	else
	{
	cout<<"敌机获胜"<<endl;
	}
}
void main()
{
	HeroFigher hf;//创建父类对象   一代战机
	EnemyFigher ef;
	HeroFigher hf2;//创建子类对象  二代战机
	
	PlayObj(&hf,&ef); //输出结果   敌机获胜
	PlayObj(&hf2,&ef); //函数对象 //输出结果  英雄机获胜  也及时这块调用了子类战机

六、多态理论基础

静态联编和动态联编

  1. c++和c相同,是静态编译型语言
  2. 在编译时,编译器自动根据指针的类型来判断指向的是一个什么对象,所以编译器认为父类指针指向的是父类对象。
  3. 由于程序没有运行,所以不可能知道父类指针指向具体是父类对象还是子类对象,从程序的安全角度,编译器假设父类指针只指向父类对象,因此编译结果为调用父类的成员函数,这种特性是静态联编。

联编是指一个程序模块、代码之间相互关联的过程

1、静态联编

静态联编是程序匹配,连接在编译阶段实现的,也称早期匹配,重载函数使用静态联编
	不写virtual关键字的就是静态联编
	也就是在编译器阶段就已经决定了函数的调用

2、动态联编

动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编(迟绑定)
在运行时候,根据具体对象(具体的类型),去执行不同对象的函数,表现为多态

七、多态原理探究

  1. 在类中声明虚函数时,编译器会在类中生成一个虚函数表
  2. 虚函数表是一个存储类成员函数指针的数据结果
  3. 虚函数表是由编译器自动生成与维护的
  4. virtual成员函数会被编译器放入虚函数表中
  5. 存在虚函数时,每个对象中都会有一个指向虚函数表的指针(vptr指针)
class Parent
{
public: 
	virtual void func()
	{
	cout<<"parent func()...."<<endl;
	}
	virtual void func(int i)
	{
    cout<<"parent func(i)...."<<endl;
	}
};
class child :public Parent
{
public : 
	virtual void func()
	{
	cout<<"child func()...."<<endl;
	}
	virtual void func(int i)
	{
    cout<<"child func(i)...."<<endl;
	}
};

在这里插入图片描述
重要的补充: 子类vptr指针是分布初始化的
child c1;
当执行父类的构造函数时,c1.vptr先指向父类的虚函数表,当父类构造函数执行完毕后,会把 c1.vptr指向子类的虚函数表

通过虚函数指针vptr调用重写函数是在程序运行时,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。
出于效率考虑,虚函数的效率较低,因此没必要将所有的成员函数都声明成虚函数

多态总结

  1. 多态实现效果 多态:同样的调用语句有不同的表现形态
  2. 多态实现3个条件 :1、有继承 2、有virtual重写 3、有父类指针指向子类对象
  3. 多态c++实现 : virtual关键字,是告诉编译器这个函数要支持多态,根据指针所指向的世纪对象类型来判断如何调用
  4. 多态理论基础:动态联编:程序运行时,去调用不同对象函数 pk 静态联编:在编译器阶段,就决定怎么调用函数
  5. 多态是设计模式的基础,是框架的即时
  6. 多态原理:是c++编译器提前布局了一个vptr指针,通过vptr指针找到一个虚函数表,找到函数的地址,来动态联编(也就是动态的迟绑定)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟道xn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值