【面試】虛函數原理

概述

含有虛函數的類,其實例化的對象都包括一個虛函數表指針vptr(virtual table pointer,虛函數表指針),該指針就在對象的開始,也就是說對象的地址就是虛函數指針的地址。

而虛函數指針指向了虛函數表。虛函數表實際上就是所有虛函數的地址數組,4B表示一個虛函數地址(入口)。

構造過程

引用:https://www.cnblogs.com/malecrab/p/5572730.html

驗證代碼

驗證環境爲Win7 64位操作系統 + VS2010 旗艦版

#include <iostream>

using namespace std;

class Parent{
public:
	long b;
	virtual void foo() {cout << "Parent foo" << endl;};
	virtual void bar() {cout << "Parent bar" << endl;};
};

class Son : public Parent{
public:
	long d;
	virtual void bar() {cout << "Son bar" << endl;};
	virtual void quz() {cout << "Son quz" << endl;};
};

typedef void(*pFunc)(void);

int main()
{
	Parent p;
	Son s;

	p.b = 100;

	s.b = 200;
	s.d = 300;

	pFunc pFun = NULL;

	cout << "父類虛函數表指針地址 0x" << (int*)(&p) << endl;
	cout << "父類虛函數表地址: 0x" << (int*)*(int*)(&p) << endl;
	cout << "父類第一個虛函數地址:0x" << (int*)*(int*)*(int*)(&p)<< endl;
	cout << "父類第二個虛函數地址:0x" << (int*)*(int*)(*(int*)(&p) + 4)<< endl;

	cout << "子類虛函數表指針地址 0x" << (int*)(&s) << endl;
	cout << "子類虛函數表地址: 0x" << (int*)*(int*)(&s) << endl;
	cout << "子類第一個虛函數地址:0x" << (int*)*(int*)*(int*)(&s)<< endl;
	cout << "子類第二個虛函數地址:0x" << (int*)*(int*)(*(int*)(&s) + 4)<< endl;
	cout << "子類第三個虛函數地址:0x" << (int*)*(int*)(*(int*)(&s) + 8)<< endl;

	//父類第一個虛函數指針	
	pFun = (pFunc)*(int*)*(int*)(&p);
	pFun();

	//父類第二個虛函數指針
	pFun = (pFunc)*(int*)(*(int*)(&p) + 4);
	pFun();

	//子類第一個虛函數指針
	pFun = (pFunc)*(int*)*(int*)(&s);
	pFun();

	//子類第二個虛函數指針
	pFun = (pFunc)*(int*)(*(int*)(&s) + 4);
	pFun();

	//子類第三個虛函數指針
	pFun = (pFunc)*(int*)(*(int*)(&s) + 8);
	pFun();

	return 0;
}

動態調試

在內存中檢視父類的地址&p,輸入'&p'後自動轉換爲0x39FD04。可以看到該地址的4B爲0xb47938,就是虛函數表指針的值。

我們看這個地址,指向的區域就是虛函數表了。可以看到分別是0xb411f4,0xb41032.


子類是一樣的,就不贅述了。

下面看下父類和子類的對象,VS中的值。可以看到vfptr的構成。但是子類對象s實際應該有三個虛函數,但是這裏並沒有體現出來第三個。


程序運行結果


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章