c++之多态

都说c++的三大特性是 继承 多态 封装

那么什么是多态呢?

1、静态多态:函数重载、运算符重载、复用函数名。
2、动态多 态:派生类和虚函数实现运行时的多态。

其实这俩个就是地址早晚绑定的区别

下面来看

​​​​​​​静态多态不用细说,下面介绍动态多态。

首先c++时允许父子类型转换如下

#include<iostream>
using namespace std;
class animal
{
public:
	void speak()
	{
		cout << "这是动物在说话" << endl;
	}
};
class dog :public animal
{
public:
	void speak()
	{
		cout << "这是小狗在说话" << endl;
	}
};
void text01(animal &a)//animal &a=d;
{
	a.speak();
}
int main()
{
	dog d;
	text01(d);
	return 0;
}

这样编译是没有问题的,但是你们觉得输出的是什么呢?

没错就是

但是我们的原意好像是想让小狗在说话吧,但是现在这个函数的地址其实就在编译阶段地址就绑定成动物的了,并不是小猫的,哪接下来如果想实现地址在运行时绑定地址怎么办呢,就是在父类函数前加一个virtual (简称虚函数)

#include<iostream>
using namespace std;
class animal
{
public:
	virtual void speak()
	{
		cout << "这是动物在说话" << endl;
	}
};
class dog :public animal
{
public:
	virtual void speak()//这里的virtual可加可不加,因为是继承父类的函数现在只是重写函数的功能
	{
		cout << "这是小狗在说话" << endl;
	}
};
void text01(animal &a)
{
	a.speak();
}
int main()
{
	dog d;
	text01(d);
	return 0;
}

 现在我们任务就完成了 

现在动态多态的满足条件就是

1、有继承关系

2、子类要重写父类的虚函数(重写就是函数返回值,参数列表都相同,只有函数内部东西不一样才叫重写)

动态多态的使用

1、父类的指针或着引用执行之类对象,就是上面函数那样。

原理剖析 

#include<iostream>
using namespace std;
class animal
{
public:
	 void speak()
	{
		cout << "这是动物在说话" << endl;
	}
};
int main()
{
	animal a;
	cout << sizeof(a) << endl;
	return 0;
}

 因为类内部的函数存储位置和数据类型存储不一样,所以这个算是空类占的内存就是1

那么加上virtual呢

#include<iostream>
using namespace std;
class animal
{
public:
	virtual  void speak()
	{
		cout << "这是动物在说话" << endl;
	}
};
int main()
{
	animal a;
	cout << sizeof(a) << endl;
	return 0;
}

 显然这个类里已经有了一个4个字节的东西,一般什么是4个字节?int?float?还有一个指针也是4个字节。那这么高级的东西,里面肯定就是一个指针了。

其实就是函数内部出现了一个vfptr(虚函数指针)用来间接指向这个函数,相当于 

class animal
{
public:
	vfptr(这是一个指针)-> 指向一个vftable(虚函数表)
};
vftable
{
      &animal::speak(这个就是我们写的函数的地址)
    就是一个指针指向一个内存里,这个内存存的就是我们写的虚函数的地址
}

现在加上子类

class animal
{
public:
	virtual  void speak()
	{
		cout << "这是动物在说话" << endl;
	}
};
class dog :public animal
{
public:
};
dog
{
    vfptr->vftable
 如果没有重写那么就是继承父类的一切东西

}
vftable
{
      &animal::speak(这个就是我们写的函数的地址)
    就是一个指针指向一个内存里,这个内存存的就是我们写的虚函数的地址
}
重写之后
class dog :public animal
{
public:
	 void speak()
	{
		cout << "这是小狗在说话" << endl;
	}
};
vftable
{
      &dog::speak(这个就是我们写的函数的地址)
    就是一个指针指向一个内存里,这个内存存的就是我们写的虚函数的地址
}

当父类指针或者引用指向子类对象的话,就发生了多态。

顺便说一下,你类中所有的虚函数都会放在虚函数表里,然后只在类中给你提供一个接口用来访问虚函数表。

简单来说,就是虚函数都放在一个机器开辟的地方,然后给你一个钥匙,这个钥匙放在你的类中,你可以通过这个钥匙去虚函数表里访问你的东西。

 现在你已经学会了多态,是不是非常简单。

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DyingLive

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

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

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

打赏作者

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

抵扣说明:

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

余额充值