1. 程式人生 > >c++::詳解虛表

c++::詳解虛表

2)虛表的內容是依據類中的虛擬函式宣告次序—填入函式指標。

【虛表的建立】:

1)基類(虛表):按照虛擬函式在基類中出現的先後次序進行一次逐個填寫虛表地址。

2)派生類(虛表):

      A、先要知道基類虛表的格式

      B、派生類對基類中那些虛擬函式進行重寫,如果重寫了,會將虛表中相同偏移位置的函式的地址進行重寫

      C、再將最後四個位元組寫為0

注意:

1、     不同物件的虛表地址相同

2、     基類型別的指標指向派生類物件,要呼叫派生類重寫的函式時,無法呼叫

【不同繼承方式下不同情況的虛表】:

(分別從繼承方式,有無重寫和是否是虛擬繼承來進行分析)

2.1單繼承的無重寫的虛表

1)說明:程式的結果:
           A:基類的列印自己的,派生類的也列印自己的 
           B:基類大小:如果有成員的話,就是成員加頭四個位元組(指向虛表的指標)派生類大小;如果有成員的話,就是成員加基類加指向虛表的指標

2)舉例程式碼:

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base::fun2()"<<endl;
	}
	int b;
};
class Derived:public Base
{
public:
	Derived()
	{}
	virtual void fun3()
	{
		cout<<"Derived::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Derived::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Derived::fun5()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base b;
	Derived d;
	cout<<"Base::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&d);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<sizeof(Base)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)程式的執行結果圖:

2.2單繼承的有重寫的虛表

1)說明:程式的結果:

           基類依然列印自己的,派生類將基類對應偏移位置的覆蓋掉

2)舉例程式碼:

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base::fun2()"<<endl;
	}
	int b;
};
class Derived:public Base
{
public:
	Derived()
	{d = 10;}
	virtual void fun0()
	{
		cout<<"Derived::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Derived::fun1()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Derived::fun5()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base b;
	Derived d;
	cout<<"Base::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&d);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<sizeof(Base)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)執行程式結果


2.3單繼承的虛擬繼承的無重寫的虛表

1)程式執行結果說明:

     A:基類列印自己的,派生類只打印自己的,並不會列印基類的
     B:基類大小:不變
        派生類大小:要加一個偏移量,所以多八個位元組
       依次是:指向派生類的虛表指標,偏移量,派生類的資料成員,
             指向基類的虛表指標,基類的資料成員
2)舉例程式碼:

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base::fun2()"<<endl;
	}
	int b;
};
class Derived:virtual public Base
{
public:
	Derived()
	{d = 20;}
	virtual void fun3()
	{
		cout<<"Derived::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Derived::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Derived::fun5()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base b;
	Derived d;
	//Base* p = &d;
	cout<<"Base::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&d);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<sizeof(Base)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)程式執行結果:


4)物件模型分析:


2.4單繼承的虛擬繼承的有重寫的虛表

1)程式結果分析:

    A:基類列印的不變,派生類將重寫的不列印,只打印自己的
    B:基類大小:不變  
       派生類的大小:和無重寫的幾乎一樣,不過多了一個用於區分物件的0
                            這個0加在了派生類資料成員和指向基類虛表的指標之間,
            這就是多出來的四個位元組
2)舉例程式碼:

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base::fun2()"<<endl;
	}
	int b;
};
class Derived:virtual public Base
{
public:
	Derived()
	{d = 20;}
	virtual void fun0()
	{
		cout<<"Derived::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Derived::fun1()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Derived::fun5()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base b;
	Derived d;
	//Base* p = &d;
	cout<<"Base::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&d);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<sizeof(Base)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)程式碼執行結果:


4)物件模型分析


2.5多繼承的無重寫的虛表

1)程式執行結果說明:

    A:基類1:列印自己的
    B: 基類2:列印自己的
    C:派生類:列印基類一,列印自己的
    D:大小:基類大小不變,派生類大小是基類一加基類2加自己的資料成員大小
2)舉例程式碼:

#include<iostream>
using namespace std;
class Base1
{
public:
	Base1()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base1::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base1::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base1::fun2()"<<endl;
	}
	int b;
};
class Base2
{
public:
	Base2()
	{
		b=20;
	}
	virtual void fun3()
	{
		cout<<"Base2::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Base2::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Base2::fun5()"<<endl;
	}
	int b;
};
class Derived:public Base1,public Base2
{
public:
	Derived()
	{d = 30;}
	virtual void fun6()
	{
		cout<<"Derived::fun6()"<<endl;
	}
	virtual void fun7()
	{
		cout<<"Derived::fun7()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"Derived::fun8()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base1 b1;
	Base2 b2;
	Derived d;
	cout<<"Base1::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b1);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Base2::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&b2);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*((int *)(&d)+2);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base1)<<endl;
	cout<<sizeof(Base2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)程式碼執行結果


4)物件模型說明


2.6多繼承的有重寫的虛表

1)程式執行結果說明:

    A: 執行結果:派生類覆蓋了基類的,其他不變
    B: 大小:同上
2)舉例程式碼:

#include<iostream>
using namespace std;
class Base1
{
public:
	Base1()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base1::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base1::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base1::fun2()"<<endl;
	}
	int b;
};
class Base2
{
public:
	Base2()
	{
		b=20;
	}
	virtual void fun3()
	{
		cout<<"Base2::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Base2::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Base2::fun5()"<<endl;
	}
	int b;
};
class Derived:public Base1,public Base2
{
public:
	Derived()
	{d = 30;}
	virtual void fun0()
	{
		cout<<"Derived::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Derived::fun1()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"Derived::fun8()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base1 b1;
	Base2 b2;
	Derived d;
	//Base* p = &d;
	cout<<"Base1::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b1);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Base2::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&b2);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*(int *)(&d);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base1)<<endl;
	cout<<sizeof(Base2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
4)物件模型解析

    這個我就不做過多的分析了。

2.8多繼承的虛擬繼承的無重寫的虛表(虛擬繼承一個基類)

1)程式執行結果說明:

     A:基類列印:基類列印自己的
     B:大小:多了偏移量,多了四個位元組
2)舉例程式碼:

#include<iostream>
using namespace std;
class Base1
{
public:
	Base1()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base1::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base1::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base1::fun2()"<<endl;
	}
	int b;
};
class Base2
{
public:
	Base2()
	{
		b=20;
	}
	virtual void fun3()
	{
		cout<<"Base2::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Base2::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Base2::fun5()"<<endl;
	}
	int b;
};
class Derived:virtual public Base1,public Base2
{
public:
	Derived()
	{d = 30;}
	virtual void fun6()
	{
		cout<<"Derived::fun6()"<<endl;
	}
	virtual void fun7()
	{
		cout<<"Derived::fun7()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"Derived::fun8()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base1 b1;
	Base2 b2;
	Derived d;
	//Base* p = &d;
	cout<<"Base1::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b1);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Base2::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&b2);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*(int *)(&d);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base1)<<endl;
	cout<<sizeof(Base2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)程式碼執行結果:


4)

2.9多繼承的虛擬繼承的無重寫的虛表(虛擬繼承所有的基類)

1)程式執行結果分析

     A:基類列印:基類列印自己的,派生類只打印自己的
     B:大小:多了偏移量,多了八個位元組
2)舉例程式碼

#include<iostream>
using namespace std;
class Base1
{
public:
	Base1()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base1::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base1::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base1::fun2()"<<endl;
	}
	int b;
};
class Base2
{
public:
	Base2()
	{
		b=20;
	}
	virtual void fun3()
	{
		cout<<"Base2::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Base2::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Base2::fun5()"<<endl;
	}
	int b;
};
class Derived:virtual public Base1,virtual public Base2
{
public:
	Derived()
	{d = 30;}
	virtual void fun6()
	{
		cout<<"Derived::fun6()"<<endl;
	}
	virtual void fun7()
	{
		cout<<"Derived::fun7()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"Derived::fun8()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base1 b1;
	Base2 b2;
	Derived d;
	//Base* p = &d;
	cout<<"Base1::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b1);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Base2::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&b2);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*(int *)(&d);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base1)<<endl;
	cout<<sizeof(Base2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}

3)程式執行結果


4)物件模型分析


2.10多繼承的虛擬繼承的有重寫的虛表(虛擬繼承一個基類)

1)程式執行結果說明       A:基類不變,派生類重寫的基類一未影響,二會覆蓋 2)舉例程式碼:
#include<iostream>
using namespace std;
class Base1
{
public:
	Base1()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base1::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base1::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base1::fun2()"<<endl;
	}
	int b;
};
class Base2
{
public:
	Base2()
	{
		b=20;
	}
	virtual void fun3()
	{
		cout<<"Base2::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Base2::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Base2::fun5()"<<endl;
	}
	int b;
};
class Derived:virtual public Base1,public Base2
{
public:
	Derived()
	{d = 30;}
	virtual void fun0()
	{
		cout<<"Derived::fun0()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Derived::fun4()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"Derived::fun8()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base1 b1;
	Base2 b2;
	Derived d;
	//Base* p = &d;
	cout<<"Base1::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b1);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Base2::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&b2);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*(int *)(&d);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base1)<<endl;
	cout<<sizeof(Base2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)程式執行結果
4)物件模型說明

2.11多繼承的虛擬繼承的有重寫的虛表(虛擬繼承所有的基類)

1)程式執行結果說明:

     A:基類不變,派生類重寫的不列印,只打印自己的
     B:大小:重寫的話,重寫幾個就多幾個位元組,多了一個用於區分的零在B1和D之間

2)舉例程式碼:

#include<iostream>
using namespace std;
class Base1
{
public:
	Base1()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base1::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base1::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base1::fun2()"<<endl;
	}
	int b;
};
class Base2
{
public:
	Base2()
	{
		b=20;
	}
	virtual void fun3()
	{
		cout<<"Base2::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"Base2::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"Base2::fun5()"<<endl;
	}
	int b;
};
class Derived:virtual public Base1,virtual public Base2
{
public:
	Derived()
	{d = 30;}
	virtual void fun0()
	{
		cout<<"Derived::fun0()"<<endl;
	}
	virtual void fun7()
	{
		cout<<"Derived::fun7()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"Derived::fun8()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base1 b1;
	Base2 b2;
	Derived d;
	//Base* p = &d;
	cout<<"Base1::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b1);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"Base2::vpf"<<endl;
	vpf* pn = (vpf*)*(int *)(&b2);
	while(*pn)
	{
		(*pn)();
		pn++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*(int *)(&d);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base1)<<endl;
	cout<<sizeof(Base2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)程式執行結果

2.12無重寫普通的菱形繼承

1)程式執行結果分析:

     A:不過加了虛擬函式,這時D記憶體結果是順序繼承:B,C1,C2,D, 
          (但是在C1和C2之間多了一個地址和一個數據。我的編譯器是這樣)
     B:  D執行結果:打印出基類B,基類C1,D
     C:執行結果的大小:28
2)舉例程式碼:

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base::fun2()"<<endl;
	}
	int b;
};
class C1:public Base
{
public:
	C1()
	{
		c1=20;
	}
	virtual void fun3()
	{
		cout<<"C1::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"C1::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"C1::fun5()"<<endl;
	}
	int c1;
};
class C2:public Base
{
public:
	C2()
	{
		c2=30;
	}
	virtual void fun6()
	{
		cout<<"C2::fun6()"<<endl;
	}
	virtual void fun7()
	{
		cout<<"C2::fun7()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"C2::fun8()"<<endl;
	}
	int c2;
};
class Derived:public C1,public C2
{
public:
	Derived()
	{
		d = 40;
	}
	virtual void fun9()
	{
		cout<<"Derived::fun9()"<<endl;
	}
	virtual void fun10()
	{
		cout<<"Derived::fun10()"<<endl;
	}
	virtual void fun11()
	{
		cout<<"Derived::fun11()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base b;
	C1 c1;
	C2 c2;
	Derived d;
	cout<<"Base::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"C1::vpf"<<endl;
	vpf* pn1 = (vpf*)*(int *)(&c1);
	while(*pn1)
	{
		(*pn1)();
		pn1++;
	}
	cout<<"C2::vpf"<<endl;
	vpf* pn2 = (vpf*)*(int *)(&c2);
	while(*pn2)
	{
		(*pn2)();
		pn2++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*(int *)(&d);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base)<<endl;
	cout<<sizeof(C1)<<endl;
	cout<<sizeof(C2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}
3)程式碼執行結果


2.13無重寫(只有一個直接基類的此處為C1)普通的菱形繼承

1)程式執行結果分析

    A:D 的列印結果:列印C1,列印D
          當然C1的大小多了八個位元組
    B:執行結果的大小36

2)舉例程式碼

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base::fun2()"<<endl;
	}
	int b;
};
class C1:virtual public Base
{
public:
	C1()
	{
		c1=20;
	}
	virtual void fun3()
	{
		cout<<"C1::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"C1::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"C1::fun5()"<<endl;
	}
	int c1;
};
class C2:public Base
{
public:
	C2()
	{
		c2=30;
	}
	virtual void fun6()
	{
		cout<<"C2::fun6()"<<endl;
	}
	virtual void fun7()
	{
		cout<<"C2::fun7()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"C2::fun8()"<<endl;
	}
	int c2;
};
class Derived:public C1,public C2
{
public:
	Derived()
	{
		d = 40;
	}
	virtual void fun9()
	{
		cout<<"Derived::fun9()"<<endl;
	}
	virtual void fun10()
	{
		cout<<"Derived::fun10()"<<endl;
	}
	virtual void fun11()
	{
		cout<<"Derived::fun11()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base b;
	C1 c1;
	C2 c2;
	Derived d;
	cout<<"Base::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"C1::vpf"<<endl;
	vpf* pn1 = (vpf*)*(int *)(&c1);
	while(*pn1)
	{
		(*pn1)();
		pn1++;
	}
	cout<<"C2::vpf"<<endl;
	vpf* pn2 = (vpf*)*(int *)(&c2);
	while(*pn2)
	{
		(*pn2)();
		pn2++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*(int *)(&d);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base)<<endl;
	cout<<sizeof(C1)<<endl;
	cout<<sizeof(C2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}

3)程式執行結果


2.13無重寫(所有的直接基類都虛擬繼承)普通的菱形繼承

1)程式執行結果分析

     A:和上面的幾乎一樣,不同的是C2必然多了八個位元組

2)舉例程式碼;

#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		b=10;
	}
	virtual void fun0()
	{
		cout<<"Base::fun0()"<<endl;
	}
	virtual void fun1()
	{
		cout<<"Base::fun1()"<<endl;
	}
	virtual void fun2()
	{
		cout<<"Base::fun2()"<<endl;
	}
	int b;
};
class C1:virtual public Base
{
public:
	C1()
	{
		c1=20;
	}
	virtual void fun3()
	{
		cout<<"C1::fun3()"<<endl;
	}
	virtual void fun4()
	{
		cout<<"C1::fun4()"<<endl;
	}
	virtual void fun5()
	{
		cout<<"C1::fun5()"<<endl;
	}
	int c1;
};
class C2:virtual public Base
{
public:
	C2()
	{
		c2=30;
	}
	virtual void fun6()
	{
		cout<<"C2::fun6()"<<endl;
	}
	virtual void fun7()
	{
		cout<<"C2::fun7()"<<endl;
	}
	virtual void fun8()
	{
		cout<<"C2::fun8()"<<endl;
	}
	int c2;
};
class Derived:public C1,public C2
{
public:
	Derived()
	{
		d = 40;
	}
	virtual void fun9()
	{
		cout<<"Derived::fun9()"<<endl;
	}
	virtual void fun10()
	{
		cout<<"Derived::fun10()"<<endl;
	}
	virtual void fun11()
	{
		cout<<"Derived::fun11()"<<endl;
	}
	int d;
};
typedef void (*vpf)();
void Printvpf()
{
	Base b;
	C1 c1;
	C2 c2;
	Derived d;
	cout<<"Base::vpf"<<endl;
	vpf* n = (vpf*)*(int *)(&b);
	while(*n)
	{
		(*n)();
		n++;
	}
	cout<<"C1::vpf"<<endl;
	vpf* pn1 = (vpf*)*(int *)(&c1);
	while(*pn1)
	{
		(*pn1)();
		pn1++;
	}
	cout<<"C2::vpf"<<endl;
	vpf* pn2 = (vpf*)*(int *)(&c2);
	while(*pn2)
	{
		(*pn2)();
		pn2++;
	}
	cout<<"Derived::vpf"<<endl;
	vpf* ppn = (vpf*)*(int *)(&d);
	while(*ppn)
	{
		(*ppn)();
		ppn++;
	}
	cout<<sizeof(Base)<<endl;
	cout<<sizeof(C1)<<endl;
	cout<<sizeof(C2)<<endl;
	cout<<sizeof(Derived)<<endl;
}
int main()
{
	Printvpf();
	return 0;
}

3)程式執行結果


最後要說明的:還有一些情況類似於上面的,我就不一一說明了,我寫的都是比較經典的情況,希望能對大家有所幫助!吐舌頭