c++多态最清晰的解释

先占个位置,稍微写点,这两天忙完了写代码版:

关于虚函数与多态,一般是用微软的解释:基类指针或引用指向派生类对象时,如果调用虚函数,则调用派生类虚函数。
我看倒不如这样来解释:另写一个函数,如  func (A&a) {}  其中一个参数是基类指针或引用,那么我在主函数中调用它时,传入参数是基类对象则是a是基类引用,传入派生类对象则a是派生类引用,那么就可以用a调用基类或者派生类虚函数,即在基类指针或引用虚函数的支持下可以实现动态绑定

借用c++primer上的一段话:当我们使用基类的引用或指针调用基类中定义的一个函数时,我们并不知道该函数真正作用的对象是什么类型,因为它可能是一个基类的对象也可能是一个派生类对象。如果该函数是虚函数,则直到运行时才会决定到底执行哪个版本,判断的依据是引用或指针所绑定的对象的真实类型。即对非虚函数的调用在编译时进行绑定。

举例如下:

#include <iostream>
using namespace std;

class father
{
public:
	virtual void fA()    
	{
		cout << "father fA" << endl;
	}
	virtual void fB()
	{
		cout << "father fB" << endl;
	}
};
class son : public father
{
public:
	virtual void fA()
	{
		cout << "son fA" << endl;
	}
	virtual void fC()
	{
		cout << "son fC" << endl;
	}
};

void func(father *obj)
{
	obj->fA();
}
int main()
{
	father *f = new father;
	son *s = new son;
	func(f);
	func(s);

	return 0;
}

输出如下:

上面就是多态的一个使用样例。

那么c++语言具体如何实现多态的呢?需要知道两个东西!

第一:虚函数表,什么意思?

就是说一个类一旦拥有虚函数,则会拥有一张虚函数表,这个表独立于对象,是属于类本身的,且这张表会被派生类继承,其中子类重写的虚函数则会使用子类的虚函数地址替代,比如上面的连个类,它们的虚函数表大致如下:

父类:

father::fA()
father::fB()

子类:

father::fA()
son::fB()
son::fC()

格式:首先是父类虚函数,然后是子类虚函数,父类被重写部分会被子类的虚函数替代

第二:位于对象头部的虚表地址,什么意思?

当一个类被实例化的时候,这个实例化对象的首地址其实是一个指向该类虚表的指针。

因此当程序运行到这里时,会通过头部的地址查找虚表中的函数来进行调用。

那么刚刚说的两点:虚表?+ 在头部?真的是这样吗,不如来验证一下,毕竟实践出真知:

计划:既然虚函数是一个函数,那么假设刚刚的两点是真的,就一定能按照上述的方法使用函数指针来调用到虚函数

代码如下:

int main()
{
	father *f = new father;
	void( *p )( );
	//首先取到对象的地址,也就是: f
	//然后地址的第一个位置存储的便是虚函数表的地址:*(int*)f
	//然后通过虚表就可以访问函数,比如第一个函数的地址就是:*(int*)*(int*)f
	p = ( void(*)( ) )*( ( int * )*( (int*) f ) ); //第一个函数
	p();
	p = ( void(*)( ) )*( ( int * )*( (int*) f ) + 1 ); //第二个函数
	p();
	return 0;
}

结果如下:

可以发现,都顺利访问到了,因此上面说的那两点是对的!

这里解释一下,为什么取地址的时候需要转换为int*,因为取地址的时候面对的是一个数值串,取地址的时候转换成int*就是告诉计算机要从这个地方取4个字节的数值,将它当作地址,况且不这么做怎么知道+1的时候移动多少呢。

那么动态绑定实现原理这里就解释完了。

最后,再啰嗦一句,可能有人被基类指针这个地方迷糊住了,说为啥必须要用基类指针,而不能派生类指针呢,其实大可不必迷惑,因为这是语法上不合逻辑的,因为派生类本来就比基类的东西多,万一访问到基类不存在的呢,这不是出了岔子?其实简而言之,如果用派生类访问基类对象,编译这一关都过不了嘻嘻。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值