C/C++—— C++編譯器是如何實現多型
關於C++中多型的基礎知識參考部落格:
C/C++—— 對多型現象的理解
C++中多型的實現原理
1.當類中宣告虛擬函式時,編譯器會在類中生成一個虛擬函式。
2.虛擬函式表是一個儲存類成員函式指標的資料結構。
3.虛擬函式表是由編譯器自動生成與維護的。
4.virtual成員函式會被編譯器放入虛擬函式表中。
5.存在虛擬函式時,每個物件中都有一個指向虛擬函式表的指標(vptr指標)。
說明1:
通過虛擬函式表指標VPTR呼叫重寫函式是在程式執行時進行的,因此需要通過定址操作才能確定真正應該呼叫的函式。而普通成員函式是在編譯時就確定了呼叫的函式。在效率上,虛擬函式的效率要低很多。
說明2:
出於效率考慮,沒有必要將所有成員函式都宣告為虛擬函式
證明vptr指標的存在
定義一個沒有虛擬函式類,檢視該類的大小。然後再將其中的函式宣告為虛擬函式,再檢視該類的大小。結果發現該類大小增大了,可以知道增加了一個指標變數,該變數就是vptr指標。
沒有虛擬函式:
#include <iostream>
using namespace std;
class Parent{
public:
Parent(int a = 0){
this->a = a;
}
//virtual void print()
void print()
{
cout << "Parent, a = " << a << endl;
}
private:
int a;
};
int main()
{
cout << "沒有虛擬函式: ";
cout << "sizeof(Parent) = " << sizeof(Parent) << endl;
return 0;
}
輸出為:
沒有虛擬函式: sizeof(Parent) = 4
有虛擬函式:
#include <iostream>
using namespace std;
class Parent{
public:
Parent(int a = 0){
this->a = a;
}
virtual void print()
{
cout << "Parent, a = " << a << endl;
}
private:
int a;
};
int main()
{
cout << "有虛擬函式: ";
cout << "sizeof(Parent) = " << sizeof(Parent) << endl;
return 0;
}
輸出為:
有虛擬函式: sizeof(Parent) = 16
這裡要解釋一下為什麼變為16了。。因為我電腦是64的linux系統,指標變數大小為8位元組,又因為位元組對齊的原因總的大小變為了16位元組。
可以去參考部落格:
C/C++——基本資料型別的大小並且sizeof(int *) = 8
C/C++—— 記憶體位元組對齊規則
物件中的VPTR指標什麼時候被初始化?
1.物件在建立的時,由編譯器對VPTR指標進行初始化
2.只有當物件的構造完全結束後VPTR的指向才最終確定
3.父類物件的VPTR指向父類虛擬函式表
4.子類物件的VPTR指向子類虛擬函式表
當定義一個父類物件的時候比較簡單,因為父類物件的VPTR指標直接指向父類虛擬函式表。
但是當定義一個子類物件的時候就比較麻煩了,因為構造子類物件的時候會首先呼叫父類的建構函式然後再呼叫子類的建構函式。當呼叫父類的建構函式的時候,此時會建立Vptr指標(也可以認為Vptr指標是屬於父類的成員,所以在子類中重寫虛擬函式的時候virtual關鍵字可以省略,因為編譯器會識別父類有虛擬函式,然後就會生成Vptr指標變數),該指標會指向父類的虛擬函式表;然後再呼叫子類的建構函式,此時Vptr又被賦值指向子類的虛擬函式表。
上面的過程是Vptr指標初始化的過程。
這是因為這個原因,在建構函式中呼叫虛擬函式不能實現多型。
見下一篇部落格:在建構函式中呼叫虛擬函式能實現多型嗎
相關文章
- C++編譯期多型與執行期多型C++編譯多型
- 剖析C++多型:用C實現簡單多型C++多型
- C++ 多型的實現及原理C++多型
- C++編譯器優化C++編譯優化
- C++多型C++多型
- C++——多型C++多型
- c++實現多型的方法 虛表C++多型
- 安裝c, c++編譯器 on AIXC++編譯AI
- C++編譯器怎麼實現異常處理1 (轉)C++編譯
- C++編譯器怎麼實現異常處理3 (轉)C++編譯
- C++編譯器怎麼實現異常處理2 (轉)C++編譯
- C++的多型C++多型
- C++多型性C++多型
- C/C++—— 對多型現象的理解C++多型
- C++編譯器認為的指標型別(靜態聯編)C++編譯指標型別
- 一文搞懂C/C++常用編譯器C++編譯
- windows 下c++編譯WindowsC++編譯
- C++ 編譯過程C++編譯
- 編譯原理——C++版桌面計算器編譯原理C++
- 如何加快C++程式碼的編譯速度C++編譯
- 情有獨鍾C++:Visual C++ .NET編譯器的新特性(轉)C++編譯
- 如何把C/C++程式編譯成Python模組-超實用C++編譯Python
- 虛擬函式表-C++多型的實現原理函式C++多型
- C++ 多型的實現原理與記憶體模型C++多型記憶體模型
- 如何分析和提高(C/C++)程式的編譯速度?C++編譯
- C++物件模型:編譯分析C++物件模型編譯
- 首個 C++ 編譯器誕生 30 週年了,來聽聽 C++ 之父暢談 C++C++編譯
- c++學習(1)--C++封裝、繼承、多型C++封裝繼承多型
- C++整理16_多型C++多型
- C++(虛擬函式實現多型基本原理)C++函式多型
- 編譯 TensorFlow 的 C/C++ 介面編譯C++
- C/C++編譯過程詳解C++編譯
- protobuf 的交叉編譯使用(C++)編譯C++
- mongodb c++ 驅動庫編譯MongoDBC++編譯
- 編譯C++ 程式的過程編譯C++
- 開心檔之C++ 多型C++多型
- 利用 C++ 11 特性實現多執行緒計數器C++執行緒
- C++實現簡易計算器C++