【C++深度探索】全面解析多态性机制(二)

07-16 974阅读

【C++深度探索】全面解析多态性机制(二)

🔥 个人主页:大耳朵土土垚 🔥 所属专栏:C++从入门至进阶 这里将会不定期更新有关C/C++的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉

【C++深度探索】全面解析多态性机制(二)

前言

我们知道C++多态实现有两个条件——一是基类的指针或引用调用虚函数,另一个是基类中有虚函数并且在派生类中实现虚函数重写;这两个条件缺一不可,这与多态实现的底层原理有关,今天我们就来学习一下多态实现的原理🥳🥳

目录

  • 前言
  • 1.虚函数表
  • 2.派生类中的虚表
    • 情况一:只有基类有虚函数,派生类没有
    • 情况二:基类和派生类中都有虚函数,并且虚函数没有被重写
    • 情况三:基类中定义虚函数,并且派生类中对该虚函数进行了重写
    • 综合这三种情况
    • 3.多态原理
      • 动态绑定与静态绑定
      • 4.多继承中的虚函数表
      • 5.结语

        1.虚函数表

        虚函数表(Virtual Function Table,VTable)是C++中实现动态多态性的一种机制。每个包含虚函数的类都有一个对应的虚函数表,用于存储该类的虚函数地址。

        虚函数表是一个包含函数指针的数组,每个函数指针指向相应虚函数的实现。

        也就是说在类中定义了虚函数,那么该类就会包含一个虚函数表来存放虚函数的函数指针,注意这里是指类中会存储虚函数表的指针来达到效果,因为如果虚函数很多,直接存储虚函数表可能会占用很多空间。

        例如:

        class Base
        {
        public:
        	virtual void Func1()
        	{
        		cout 
        	cout 
        private:
        	int _b = 1;
        };
        class Derive :public Base
        {
        public:
        	virtual void Func2()
        	{
        		cout 
        	Derive d;
        	return 0;
        }
        
        public:
        	virtual void Func1()
        	{
        		cout 
        private:
        	int _d = 2;
        };
        int main()
        {
        	Derive d;
        	return 0;
        }
        
        public:
        	virtual void Func1()
        	{
        		cout 
        public:
        	virtual void Func2()
        	{
        		cout 
        	Derive d;
        	return 0;
        }
        
        	// 依次取虚表中的虚函数指针打印并调用。调用就可以看出存的是哪个函数
        	cout 
        		printf(" 第%d个虚函数地址 :0X%x-", i, vTable[i]);
        		VFPTR f = vTable[i];
        		f();//调用该函数
        	}
        	cout 
        	Base b;
        	Derive d;
        	//打印b对象中虚函数的地址
        	VFPTR* vTableb = (VFPTR*)(*(int*)&b);
        	PrintVTable(vTableb);
        	
        	//打印d对象中虚函数的地址
        	VFPTR* vTabled = (VFPTR*)(*(int*)&d);
        	PrintVTable(vTabled);
        }
        
        public:
        	virtual void Func1()
        	{
        		cout 
        public:
        	virtual void Func1()//重写虚函数Fun1()
        	{
        		cout 
        	Base b;
        	Derive d;
        	return 0;
        }
        
        public:
        	virtual void Func1()
        	{
        		cout 
        		cout 
        		cout 
        public:
        	virtual void Func1()//重写
        	{
        		cout 
        	Base b;
        	Derive d;
        }
        
        	int i = 0;
        	static int j = 1;
        	int* p1 = new int;
        	const char* p2 = "aaaaa";
        	Base b;
        	Derive d;
        	printf("栈:%p\n", &i);
        	printf("静态区:%p\n", &j);
        	printf("堆:%p\n", p1);
        	printf("常量区:%p\n", p2);
        	printf("Base虚表地址:%p\n", *(int*)&b);
        	printf("Derive虚表地址:%p\n", *(int*)&d);
        	return 0;
        }
        
        public:
        	virtual void BuyTicket() { cout 
        public:
        	virtual void BuyTicket() { cout 
        	p.BuyTicket();
        }
        int main()
        {
        	Person Black;
        	Func(Black);
        	Student tutu;
        	Func(tutu);
        	return 0;
        }
        
        public:
        	virtual void func1() { cout  cout 
        public:
        	virtual void func1() { cout  cout 
        public:
        	virtual void func1() { cout  cout 
        	cout 
        		printf(" 第%d个虚函数地址 :0X%x,-", i, vTable[i]);
        		VFPTR f = vTable[i];
        		f();
        	}
        	cout 
        	Derive d;
        	//第一个虚表地址
        	VFPTR* vTableb1 = (VFPTR*)(*(int*)&d);
        	PrintVTable(vTableb1);
        	//找到第二个虚表的地址
        	VFPTR* vTableb2 = (VFPTR*)(*(int*)((char*)&d + sizeof(Base1)));
        	PrintVTable(vTableb2);
        	return 0;
        }
        
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]