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

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

相关推荐
颜酱10 小时前
图的数据结构:从「多叉树」到存储与遍历
javascript·后端·算法
saltymilk15 小时前
使用 C++ 模拟 ShaderLanguage 的 swizzle
c++·模板元编程
zone773915 小时前
006:RAG 入门-面试官问你,RAG 为什么要切块?
后端·算法·面试
CoovallyAIHub18 小时前
OpenClaw 近 2000 个 Skills,为什么没有一个好用的视觉检测工具?
深度学习·算法·计算机视觉
CoovallyAIHub18 小时前
CVPR 2026 | 用一句话告诉 AI 分割什么——MedCLIPSeg 让医学图像分割不再需要海量标注
深度学习·算法·计算机视觉
CoovallyAIHub18 小时前
Claude Code 突然变成了 66 个专家?这个 5.8k Star 的开源项目,让我重新理解了什么叫"会用 AI"
深度学习·算法·计算机视觉
兆子龙18 小时前
前端哨兵模式(Sentinel Pattern):优雅实现无限滚动加载
前端·javascript·算法
xlp666hub21 小时前
Leetcode第五题:用C++解决盛最多水的容器问题
linux·c++·leetcode
CoovallyAIHub1 天前
9个视觉语言模型工厂实测:Qwen 87.9%碾压全场,你的显卡能跑哪个?
算法
SparkX开源AI知识库1 天前
手摸手带你安装OpenClaw并对接飞书
算法·架构