1. 程式人生 > >繼承裡既有虛繼承也有虛擬函式繼承(即既有虛基表,也有虛擬函式表)

繼承裡既有虛繼承也有虛擬函式繼承(即既有虛基表,也有虛擬函式表)

對於單一的虛繼承可參考這篇部落格:
https://blog.csdn.net/sophia__yu/article/details/82791522
對於有虛擬函式繼承可參考這篇部落格:
https://blog.csdn.net/sophia__yu/article/details/82791592
接下來將會介紹既有虛繼承也有多型的繼承:
首先看程式碼:

#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
/////////////虛基表和虛表
class A
{
public:
	virtual void f1()
	{
		cout << "A::f1()" << endl;
	}
	virtual void f2()
	{
		cout << "A::f2()" << endl;
	}
public:
	int _a;
};
class B :virtual public A
{
public:
	virtual void f1()  //重寫虛擬函式
	{
		cout << "B::f1 ()" << endl;
	}
	virtual void f3()  // B重新定義的虛擬函式
	{
		cout << "B::f3()" << endl;
	}
	//另外B繼承了A的f2函式
public:
	int _b;
};
class  C : virtual public A
{
public:
	virtual void f1()  // C重寫了虛擬函式f1
	{
		cout << "C::f1()" << endl;
	}
	virtual void f3()  // C重新定義了虛擬函式f3
	{
		cout << "C::f3()" << endl;
	}
	//另外C繼承了A的虛擬函式f2
public:
	int _c;
};
class D : public B, public C
{
public:
	virtual void f1()
	{
		cout << "D::f1()" << endl;
	}
	virtual void f4()
	{
		cout << "D::f4()" << endl;
	}
public:
	int _d;
};
typedef void(*FUNC)();

void printVtable(int *vfter)
{
	cout << "虛表地址:" << vfter << endl;
	for (int i = 0; vfter[i] != 0; i++) //因為虛表最後一個元素是0
	{
		printf("第%d個虛擬函式地址:0x%x,->", i, vfter[i]);
		FUNC f = (FUNC)vfter[i];
		f(); //呼叫該虛擬函式
	}
	cout << endl;
}
int main()
{
	D d;
	d._a = 1;
	d._b = 2;
	d._c = 3;
	d._d = 4;
	cout << sizeof(d) << endl;
	int *vfptr1 = (int*)(*((int*)(&d))); //B 的虛表指標
	printVtable(vfptr1);
	int *vfptr2 = (int*)(*((int*)(((char*)(&d)) + 12)));//  C的虛表指標
	printVtable(vfptr2);
	int *vfptr = (int*)(*((int*)(((char*)(&d)) + 28)));  //  公共虛表指標
	printVtable(vfptr);
	system("pause");
	return 0;
}

在這裡插入圖片描述
具體解釋如下:
在這裡插入圖片描述
注:主要是在A類中,不論是不是冗餘資料,都要放在公共資料塊即最下邊(相對編譯器)。