天天看點

c++中虛函數,虛函數表,虛函數表指針

在C++中随處可見封裝,繼承,多态。

多态的實作,是基于虛函數的繼承,虛函數則是基于虛函數表和虛函數表指針。

用一個示例介紹虛函數表指針通路虛函數,更易于友善了解虛函數,程式中也有注釋

// virtual-table.cpp
#include <iostream>

using namespace std;

class A {
public:
	A() {
		cout << __func__ << endl;
	}

	virtual void fun() {
		cout << "A : " << __func__ << endl;
	};

	virtual void bar() {
		cout << "A : " << __func__ << endl;
	};

};

class B : public A {
public:
	B() : A() {
		cout << __func__ << endl;
	}

	void fun() {
		cout << "B : " << __func__ << endl;
	}

	void bar() {
		cout << "B : " << __func__ << endl;
	}

};


int main (int argc, char *argv[])
{
	typedef void (*pfun) (void);
	
	int bits = sizeof(int *);

	B b;
	B b1;

	cout << "-------- 虛函數表 -----------" << endl;
	// 虛表位址存在于每個執行個體對象的首位址處
	// 虛函數表位址是同一個位址,說明虛表隻屬于該類
	// 不屬于該類的執行個體子對象
	cout << *(int *)*(int *)&b << endl;
	cout << *(int *)*(int *)&b1 << endl;

	pfun fun = NULL;
	pfun fun1 = NULL;
	
	cout << "----- 利用虛表調用函數 ------" << endl;
	fun = (pfun)*((int *)*(int *)&b);
	fun();
	if (8 == bits) {
		fun = (pfun)*((int *)*(int *)&b + 2);
	}
	else if (4 == bits) {
		fun = (pfun)*((int *)*(int *)&b + 1);
	}
	fun();

	fun1 = (pfun)*((int *)*(int *)&b);
	fun1();
	if (8 == bits) {
		fun1 = (pfun)*((int *)*(int *)&b + 2);
	}
	else if (4 == bits) {
		fun1 = (pfun)*((int *)*(int *)&b + 1);
	}
	fun1();

	// 多态
	cout << "---------- 指針 -------------" << endl;
	A *a = new B;
	a->fun();
	
	cout << "---------- 引用 -------------" << endl;
	A &a1 = b;
	a1.bar();

	return 0;
}
           

編譯,運作

[email protected] $ g++ virtual-table.cpp
[email protected] $ ./a.out 
A
B
A
B
-------- 虛函數表 -----------
4197940
4197940
----- 利用虛表調用函數 ------
B : fun
B : bar
B : fun
B : bar
---------- 指針 -------------
A
B
B : fun
---------- 引用 -------------
B : bar