22.多态(下)

多态原理:

虚函数表指针实际叫函数指针数组

这是虚函数表指针,这是个指针指向这张表也就是指向这个数组。

cpp 复制代码
class Person {
public:
	void BuyTicket() { cout << "买票-全价" << endl; }
protected:
	string _name;
};

class Student : public Person {
public:
	virtual void BuyTicket() { cout << "买票-打折" << endl; }

protected:
	int _id;
};

class Soldier : public Person {
public:
	virtual void BuyTicket() { cout << "买票-优先" << endl; }

protected:
	string _codename; // 代号
};

void Func(Person* ptr)
{
	// 这里可以看到虽然都是Person指针Ptr在调用BuyTicket
	// 但是跟ptr没关系,而是由ptr指向的对象决定的。
	ptr->BuyTicket();
}

int main()
{
	// 其次多态不仅仅发生在派生类对象之间,多个派生类继承基类,重写虚函数后
	// 多态也会发生在多个派生类之间。
	Person ps;
	Student st;
	Soldier sr;

	Func(&ps);
	Func(&st);
	Func(&sr);

	return 0;
}

各类的虚函数表有各自的虚函数,继承父类还有自己的成员。

怎么样能指向谁调用谁,编译器检查语法也是看满足多态吗,满足,编译这段指令时候就把这段指令变成 到指针指向这个对象的里面的虚表去找,

这个ptr无论传谁我看到的都是父类,

无论ptr指向person student codename 看到的都是person,切片以后看到的也是person,只是有可能是person,也有可能是子类切片切出来的person对象。汇编转换成指令是指针找到对象,去这个对象四个字节或者八个字节据情况而定取这个指针,通过这个指针找到函数指针的数组,这个表,在这个表里找到虚函数

父类是父类虚函数,子类是子类重写的虚函数。

person的virtual去掉就不满足多态

满足多态生成一组汇编,不满足多态生成一组汇编。不满足多态跟指向就无关,调用的都是父类

左边就是通过虚函数表指针不断找,调用

父类虚表放父类虚函数子类虚表放子类虚函数。某种程度上这也是重写的意义,执行的指令一样,但是对象的续表不一样,所以指向不同对象调用不同虚函数。

为甚不把虚函数直接放对象而放到一个表,因为很多对象可共享。同类型虚函数表是一样的,否则太冗余。

派生类的虚函数表指针是他继承的基类那一部分继承下来的,那一部分指针跟基类是不一样的。

继承类的虚函数表先把基类的虚函数表复制,然后继承类有重写的,就覆盖,没重写的就加进去,加进去的vs看不了,调用内存看,

第三个很接近,基本上确定是

拿到对象的头四个字节,就是虚函数表的地址,

强转成int* 解引用就是看头上四个字节,头上四个字节值就是指向虚表 的地址,

cpp 复制代码
int main()
{
	int i = 0;
	static int j = 1;
	int* p1 = new int;
	const char* p2 = "xxxxxxxx";
	printf("栈:%p\n", &i);
	printf("静态区:%p\n", &j);
	printf("堆:%p\n", p1);
	printf("常量区:%p\n", p2);

	Base b;
	Derive d;
	Base* p3 = &b;
	Derive* p4 = &d;
	printf("Person虚表地址:%p\n", *(int*)p3);
	printf("Student虚表地址:%p\n", *(int*)p4);
	printf("虚函数地址:%p\n", &Base::func1);
	printf("普通函数地址:%p\n", &Base::func5);
	return 0;
}

打印虚函数和普通函数就,是为了证明,他两在一个区域。只是虚函数地址又放到了虚表里面,成员函数取地址前面加&。

可以认为虚函数在VS下放到常量区

放到栈肯定不合理,函数结束,虚表销毁,两个函数,一个函数结束虚表销毁,不行。堆可以也不太合理,动态开辟没人去释放,系统自动释放倒是可以,静态区常量区更合理。取决于开发人员

相关推荐
YLCHUP11 分钟前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
xiaoye-duck22 分钟前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
思麟呀44 分钟前
背包DP(01背包+完全背包)
c++·算法
Funlang2 小时前
龙芯上的 Fun:从跑起来到机器码
开发语言·龙芯
总要学点什么2 小时前
第104篇:三维特效-流动墙体效果——让贴图沿墙流动,它却只肯走一条对角线
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
笑容掩饰我的失落2 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
旖旎夜光2 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习
ShineWinsu2 小时前
对于Qt:QTabWidget常见属性的解析
开发语言·数据库·c++·qt·浏览器·qtabwidget·标签页
Pniubi3 小时前
力扣24. 两两交换链表中的节点(递归)
算法·leetcode·链表
普通人63 小时前
WebGL与WebGPU入门指南
开发语言·webgl·1024程序员节