單繼承與多繼承中的虛函數表和虛函數指針

首先,我們瞭解一下何爲單繼承,何爲多繼承??

單繼承:一個子類只有一個直接父類。

多繼承:一個子類有兩個或多個直接父類。

單繼承中的虛函數表分析:

示例程序:

#include <iostream>
using namespace std;

typedef void(*FUNC)();

class Base
{
public:
	virtual void func1()
	{
		cout << "Base::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base::func2()" << endl;
	}
private:
	int _b;
};

class Derive :public Base
{
public:
	virtual void func1()
	{
		cout << "Derive::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Derive::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Derive::func4()" << endl;
	}
private:
	int _d;
};
void PrintVfptr(int* vptr)
	//打印虛函數表
{
	cout << "虛函數表: " << vptr << endl;
	for (int i = 0; vptr[i] != 0; ++i)
	{
		printf("第%d個虛函數:%p  >> ", i, vptr[i]);
		FUNC f = (FUNC)(vptr[i]);
		f();
	}
}

void Test()
{
	Base b;
	Derive d;

	int* vptrBase = (int*)(*(int*)(&b));
	int* vptrDeri = (int*)(*(int*)(&d));

	PrintVfptr(vptrBase);
	cout << endl;
	PrintVfptr(vptrDeri);

}

int main()
{
	Test();
	system("pause");
	return 0;
}

程序運行結果:

Base類(基類)的虛函數表:

wKioL1bcEMbyJxs-AAAQf1oQ-Ns235.png

Derive類(派生類)的虛函數表:

wKiom1bcEHuxOB0QAAAcF7C983I617.png

結論:

如果有虛函數表,那麼只有一個虛函數表,並且按照虛函數聲明的順序順序排列,派生類的虛函數緊接着基類的虛函數排列


多繼承中的虛函數表分析:

示例代碼:

#include <iostream>
using namespace std;

typedef void(*FUNC)();
class Base
{
public:
	virtual void func1() = 0;
	virtual void func2() = 0;
};

class Base1:public Base
{
public:
	virtual void func1()
	{
		cout << "Base1::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base1::func2()" << endl;
	}
private:
	int _b1;
};

class Base2: public Base
{
public:
	virtual void func1()
	{
		cout << "Base2::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base2::func2()" << endl;
	}
private:
	int _b2;
};


class Derive : public Base1, public Base2
{
public:
	virtual void func1()
	{
		cout << "Derive::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Derive::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Derive::func4()" << endl;
	}
private:
	int _d;
};

void PrintVfptr(Base* b)
{
	int* vTable1 = (int*)(*(int*)b);
	cout << "虛函數表指針:" << vTable1 << endl;
	for (int i = 0; vTable1[i] != 0; ++i)
	{
		printf("第%d個虛函數指針: %p   >>", i, vTable1[i]);
		FUNC f = (FUNC)vTable1[i];
		f();
	}
	//int* vTable2 = (int*)(*((int*)b + sizeof(Base1) / 4));
	int* vTable2 = (int*)(*((int*)((char*)b + sizeof(Base1))));
	cout << "虛函數表指針:" << vTable2 << endl;
	for (int i = 0; vTable2[i] != 0; ++i)
	{
		printf("第%d個虛函數指針: %p   >>", i, vTable2[i]);
		FUNC f = (FUNC)vTable2[i];
		f();
	}
}

void Test()
{
	Base1 b1;
	Base2 b2;
	Derive d;
	PrintVfptr(&b1);
	cout << endl;
	PrintVfptr(&b2);
	cout << endl;
	PrintVfptr((Base1*)&d);
}

int main()
{
	Test();
	system("pause");
	return 0;
}

程序運行結果:

Base1的虛函數表:

wKioL1bcFcSzAXRSAAAX-leGeyg336.png

Base2的虛函數表:

wKioL1bcFq2xTaMeAAAQJsD_jQU490.png

Derive的虛函數表:(有兩個虛函數表)

wKioL1bcFyCAR3u_AAAq7ZbMpMs067.png

多繼承中的菱形繼承:

示例代碼:

#include <iostream>
using namespace std;

typedef void(*FUNC)();
class Base
{
public:
	virtual void func1()
	{
		cout << "Base::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base::func2()" << endl;
	}
private:
	int _b;
};

class Parent1 :public Base
{
public:
	virtual void func1()
	{
		cout << "Parent1::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Parent1::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Parent1::func4()" << endl;
	}
	virtual void func5()
	{
		cout << "Parent1::func5()" << endl;
	}
private:
	int _p1;
};

class Parent2 :public Base
{
public:
	virtual void func1()
	{
		cout << "Parent2::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Parent2::func3()" << endl;
	}
	virtual void func6()
	{
		cout << "Parent2::func6()" << endl;
	}	
	virtual void func7()
	{
		cout << "Parent2::func7()" << endl;
	}
private:
	int _p2;
};

class Child :public Parent1, public Parent2
{
public:
	virtual void func1()
	{
		cout << "Child::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Child::func3()" << endl;
	}
	virtual void func4()
	{
		cout << "Child::func4()" << endl;
	}
	virtual void func6()
	{
		cout << "Child::func6()" << endl;
	}	
	virtual void func8()
	{
		cout << "Child::func8()" << endl;
	}
private:
	int _c;
};

void PrintVfptr(int* vptr)
	//打印虛函數表
{
	cout << "虛函數表: " << vptr << endl;
	for (int i = 0; vptr[i] != 0; ++i)
	{
		printf("第%d個虛函數:%p  >> ", i, vptr[i]);
		FUNC f = (FUNC)(vptr[i]);
		f();
	}
}
void Test()
{
	Base b;

	Parent1 p1; 
	Parent2 p2;

	Child c;

	int* vptr_B = (int*)(*(((int*)(&b))));

	int* vptr_P1 = (int*)(*(((int*)(&p1))));

	int* vptr_P2= (int*)(*(((int*)(&p2))));

	PrintVfptr(vptr_B);
	cout << endl;

	PrintVfptr(vptr_P1);
	cout << endl;

	PrintVfptr(vptr_P2);
	cout << endl;

	int* vptr_C_1 = (int*)(*(((int*)(&c))));
	int* vptr_C_2 = (int*)(*(int*)((char*)(&c) + sizeof(Parent1)));

	PrintVfptr(vptr_C_1);
	cout << endl;
	PrintVfptr(vptr_C_2);
	cout << endl;
}
int main()
{
	Test();
	system("pause");
	return 0;
}

運行結果:

wKioL1bcGALwhph7AABvr4tJVO0897.png其中,Child有兩個虛函數表,因爲它有兩個直接父類。


總結:多繼承中會有多個虛函數表,幾重繼承就會有幾個虛函數表。這些虛函數表會按照派生的順序依次排列。如果子類改寫了父類的虛函數,那麼就會用子類自己的虛函數覆蓋相應的父類虛函數;如果子類有新的虛函數,那麼就添加到第一個虛函數表的末尾。

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