C++虚函数与多态记录

C++虚函数与多态记录

代码

// 虚函数和多态
/*
 基类成员函数用virtual修饰
 1. 基类大小多出来4个字节
	指针 _vfptr
	_vfptr 指向一个  函数指针数组
	数组中保存所有虚函数的地址
2. 派生类继承基类, 会继承基类的函数指针数组里的元素
3. 如果派生类有重写,即在派生类里面有与基类重名的函数, 那么重写后的函数地址会覆盖函数指针
数组里的元素
4. 调用函数时, 会去虚函数表中找函数
*/

#include "pch.h"

#include <iostream>

using namespace std;

class A
{
	int n;
public:
	virtual void show() { cout << "A show" << endl; }
	virtual void show2() { cout << "A show2" << endl; }

};
class B :public A
{
public:
	void show() { cout << "B show" << endl; }
};

// 给没有返回值,没有参数的函数指针取个别名,叫做pFUNC
// 那么pFUNC 就是指向这样的函数的指针类型
typedef void(*pFUNC)();



class C :public A
{
public:
	void show() { cout << "C show" << endl; }
};
int main()
{
	int num = 100;
	int *po = &num;
	cout << "Hello============== World!\n";
	A a;
	B b;
	C c;

	/*
	A* p = NULL;
	p = &b;
	p->show();

	p = &c;
	p->show();

	cout << "====================================" << endl;
	*/
	// pvfptr 指向 B类的对象b, 获得虚函数表地址 pvfptr
	int* pvfptr;
	pvfptr = (int*)&b;                         // 强行把&b(B*)转成(int*)类型 ,取得虚函数表的地址
	cout << "&b:     " << &b << endl;        // 
	cout << "pvfptr: " << pvfptr << endl;    // 
	// 获得对象b中的虚函数表的地址,就是虚函数表这个数组的首地址
	int* _vfptr;
	_vfptr = (int*)*pvfptr;                   // 然后,再次取值就可以得到第一个虚函数的地址了

	cout << "*pvfptr: " << *pvfptr << endl;
	cout << "(int*)*pvfptr: " << (int*)*pvfptr << endl;

	//int** _vfptr;
	//_vfptr = &pvfptr;




	cout << "_vfptr: " << _vfptr << endl;           // 获得虚函数表首地址
	int* pfunc1 = (int*)*_vfptr;
	cout << "pfunc1: " << pfunc1 << endl;          // 获得虚函数表第一个函数地址
	int* pfunc2 = (int*)*(_vfptr + 1);
	cout << "pfunc2: " << pfunc2 << endl;          // 获得虚函数表第二个函数地址

	

	pFUNC pf1 = (pFUNC)pfunc1;
	pf1();
	pFUNC pf2 = (pFUNC)pfunc2;
	pf2();

	pFUNC pf3 = (pFUNC)_vfptr;
	pf3();
	pFUNC pf4 = (pFUNC)_vfptr;
	pf4();

	return 0;

}

/*

_vfptr: 0046F084
pfunc1: 00401096
pfunc2: 00401285
B show
A show2

*/



VS 内存地址

在这里插入图片描述

代码对应的图示

在这里插入图片描述

发布了28 篇原创文章 · 获赞 4 · 访问量 1217

猜你喜欢

转载自blog.csdn.net/weixin_41888257/article/details/103329284