一. 多態的實現--虛表
1.多態就是多種形態。在C++中,對同一父類和子類構造出的不同對象發出同一條指令,需要它們完成不同的工作,就需要在父類和子類寫出相同函數名的函數方法,并用虛函數區分它們。父類的指針/引用調用重寫的虛函數,當父類指針/引用指向父類對象時調用的是父類的虛函數,指向子類對象時調用的是子類的虛函數。
2.虛函數表是通過一塊連續內存來存儲虛函數的地址。這張表解決了繼承、虛函數(重寫)的問題。在有虛函數的對象實例中都存在一張虛函數表,虛函數表就像一張地圖,指明了實際應該調用的虛函數函數。
//帶虛函數的類
class Base
{
public:
virtual void func1()
{
cout << "Base::func1()" << endl;
}
virtual void func2()
{
cout << "Base::func2()" << endl;
}
private:
int a;
};
void Test1()
{
Base b1;
}3.帶虛函數的類的模型結構

4.同一類的對象共用同一虛表
void Test2()
{
Base b1, b2, b3;
}
二. 單繼承&多繼承的對象模型
1.單繼承:
class Base
{
public:
virtual void func1()
{
cout << "Base::func1()" << endl;
}
virtual void func2()
{
cout << "Base::func2()" << endl;
}
private:
int a;
};
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 b;
};
typedef void(*FUNC) ();
void PrintVTable(int* VTable)
{
cout << " 虛表地址>" << VTable << endl;
for (int i = 0; VTable[i] != 0; ++i)
{
printf(" 第%d個虛函數地址 :0X%x,->", i, VTable[i]);
FUNC f = (FUNC)VTable[i];
f();
}
cout << endl;
}
void Test1()
{
Base b1;
Derive d1;
int* VTable1 = (int*)(*(int*)&b1);
int* VTable2 = (int*)(*(int*)&d1);
PrintVTable(VTable1);
PrintVTable(VTable2);
}
2.多繼承
class Base1
{
public:
virtual void func1()
{
cout << "Base1::func1" << endl;
}
virtual void func2()
{
cout << "Base1::func2" << endl;
}
private:
int b1;
};
class Base2
{
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;
}
private:
int d1;
};
typedef void(*FUNC) ();
void PrintVTable(int* VTable)
{
cout << " 虛表地址>" << VTable << endl;
for (int i = 0; VTable[i] != 0; ++i)
{
printf(" 第%d個虛函數地址 :0X%x,->", i, VTable[i]);
FUNC f = (FUNC)VTable[i];
f();
}
cout << endl;
}
void Test1()
{
Derive d1;
int* VTable = (int*)(*(int*)&d1);
PrintVTable(VTable);
// Base2虛函數表在對象Base1后面
VTable = (int *)(*((int*)&d1 + sizeof(Base1) / 4));
PrintVTable(VTable);
}
三. 靜態多態和動態多態
1.靜態多態就是重載,因為是在編譯期決議確定,所以稱為靜態多態。
2.動態多態就是通過繼承重寫基類的虛函數實現的多態,因為是在運行時決議確定,所以稱為動態多態。
class Base
{
public:
virtual void func1()
{
cout << "Base::func1" << endl;
}
virtual void func2()
{
cout << "Base::func2" << endl;
}
void display()
{
cout << "display()" << endl;
}
void display(int i)
{
cout << "display(int i)->" << i << endl;
}
private:
int a;
};
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 b;
};
void func(Base& b)
{
b.func1();
b.display();
b.display(10);
}
void Test1()
{
Base b1;
Derive d1;
func(b1);
func(d1);
}
四. 菱形虛擬繼承的對象模型
class A
{
public:
virtual void FunTest1()
{
cout << "A::FunTest1()" << endl;
}
virtual void FunTest2()
{
cout << "A::FunTest2()" << endl;
}
private:
int _a;
};
class B1 :virtual public A
{
public:
virtual void FunTest3()
{
cout << "B1::FunTest3()" << endl;
}
virtual void FunTest4()
{
cout << "B2::FunTest4()" << endl;
}
private:
int _b1;
};
class B2 :virtual public A
{
public:
virtual void FunTest1()
{
cout << "B2::FunTest1()" << endl;
}
virtual void FunTest4()
{
cout << "B2::FunTest4()" << endl;
}
private:
int _b2;
};
class C :public B1, public B2
{
public:
virtual void FunTest1()
{
cout << "C::FunTest1()" << endl;
}
virtual void FunTest5()
{
cout << "C::FunTest5()" << endl;
}
private:
int _c;
};
void Test1()
{
C c;
c.FunTest5();
}
可見,在虛擬繼承中,無論是幾重繼承,最終子類的虛函數表總是與繼承列表的第一個父類的虛函數表合并在一起,但是有覆蓋的虛函數,自然去覆蓋父類的同名虛函數,并合并在該父類的虛表中。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。