多态最强者--虚函数表

多态简介

面向对象的三大特征:封装、继承、多态,其中比较复杂的就是继承和多态了,这两者均是代码复用的方式,这里重点讲述多态。
C++语言的多态一般分为静态多态和动态多态,静态多态主要为重载和模板,动态多态则是重写。

虚函数表

在一个类的成员函数前面加上关键字virtual,那么这个类就有开头就会有一个虚函数表,虚函数表里存储的是每个虚函数的指针,注意每个类只有一个虚函数表,如果生成一个函数对象,那么这个函数对象就有在对象的开始地址生成一个指向虚函数表的指针(虚表指针)(注意,如果对一个类求大小,其实就是对这个类的实例求大小sizeof)。

验证虚函数表只存在一份

后面的多个实验均是基于这里的代码
首先定义三个类:

#include<iostream>
#include<stdio.h>

using namespace std;

class A {
public:
	virtual void fun() {
		std::cout << "A::fun\n";
	}
	virtual void sex()
	{
		std::cout << "A::sex\n";
	}
};
class B1 :public A {
public:
	void fun() {
		std::cout << "B1::fun\n";
	}
};
class B2 :public A {
public:
	void fun() {
		std::cout << "B2::fun\n";
	}
};

在main函数中,对实例不断的取地址,可以得到函数的指针地址

int main()
{
	A* pObj[3] = {
		new A,
		new B1,
		new B2
	};
	for (A* pTmp : pObj) {
		pTmp->fun();
	}

	//获取虚函数表地址、虚函数地址
	int objAddress = (int)&pObj[0];//--对象地址
	int vtfAddress = *(int *)objAddress;//--虚函数表地址
	int funAdress = *(int *)vtfAddress;//--首个虚函数地址
	cout << "objAddress:" << objAddress<< endl;
	cout << "vtfAddress:" << vtfAddress << endl;
	cout << "funAdress:" << *(int*)funAdress << endl;
	//
	int objAddress2 = (int)&pObj[1];//--对象地址
	int vtfAddress2 = *(int *)objAddress2;
	int funAdress2 = *(int *)vtfAddress2;
	cout << "objAddress2:" << objAddress2 << endl;
	cout << "vtfAddress2:" << vtfAddress2 << endl;
	cout << "funAdress2:" << *(int*)funAdress2 << endl;
	void(*pfun)();
	pfun = (void(*)())(*(int *)funAdress);
	pfun();
	system("pause");
	return 0;
}

注意上述代码中的地址和整形之间的关系,32位操作系统中,一个地址其实用的是无符号32位数字unsigned int。

没有函数对象调用虚函数

虚函数是在编译时期生成的,所以只要获取函数的函数指针(地址),那么就可以像普通的函数调用那样对函数进行调用,例如上图的例子中,我们将虚函数指针赋给了函数指针

void(*pfun)();//变量声明/定义遵循“右左法则”--最先结合的就是最终的变量类型
pfun = (void(*)())(*(int *)funAdress);//=右边是表达式:表达式遵循运算符的优先级策略,最后的结果才是最终的结果

那么可以将生成的函数对象删除,同样可以调用虚函数。

(void *)指针

指针的不管指向的对象是什么类型,其本质是一个 unsigned int 的数值,

修改虚函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值