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下放到常量区

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

相关推荐
凡人叶枫4 小时前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
CSDN_RTKLIB4 小时前
使用三方库头文件未使用导出符号情景
c++
zheyutao4 小时前
字符串哈希
算法
春日见4 小时前
车辆动力学:前后轮车轴
java·开发语言·驱动开发·docker·计算机外设
A尘埃4 小时前
保险公司车险理赔欺诈检测(随机森林)
算法·随机森林·机器学习
锐意无限4 小时前
Swift 扩展归纳--- UIView
开发语言·ios·swift
低代码布道师4 小时前
Next.js 16 全栈实战(一):从零打造“教培管家”系统——环境与脚手架搭建
开发语言·javascript·ecmascript
念何架构之路5 小时前
Go进阶之panic
开发语言·后端·golang
亓才孓5 小时前
[Properties]写配置文件前,必须初始化Properties(引用变量没执行有效对象,调用方法会报空指针错误)
开发语言·python
傻乐u兔5 小时前
C语言进阶————指针3
c语言·开发语言