2012-02-26 50 views
12

我想知道一個類的大小的詳細說明。 我想知道是否只有數據成員&成員函數沒有任何虛擬關鍵字,那麼爲什麼類的大小隻取決於數據成員。 對於例如:爲什麼課堂大小僅取決於數據成員而不取決於成員函數?

class A { 
    int a; 
public: 
    int display() { 
    cout << "A=" << a << endl; 
    } 
}; 

當我檢查sizeof(A)我發現,它是4字節。爲什麼是這樣?爲什麼成員函數對A類的大小沒有影響?

謝謝

+0

看看[這個stackoverflow答案](http://stackoverflow.com/questions/9439240/sizeof-class-with-int-function-virtual-function-in-c)。它應該清除你的疑惑。 – vvnraman 2012-02-26 09:50:43

回答

13

因爲類的函數沒有保存在對象本身內部。從C編程的角度考慮,A的每個函數都需要一個祕密參數,這個指針,所以實際上它們只是帶有一個額外參數的函數。

例如想象它是這樣的:

int display(A* thisptr) 
{ 
    //do something 
    printf("%d",thisptr->a); 
    return; 
} 

所以顯示功能被保存爲只是一個額外的參數的簡單功能。儘管名稱取決於編譯器,但名稱已經發生了變化。

我相信不同的規則適用於涉及函數指針的虛函數,但由於我不確定也許其他人可以在這個問題上啓發我們。

2

就像常規的C函數一樣,C++方法只是內存中的一個地址,當執行被調用時跳轉到該地址。唯一的區別是第一個參數,它是指向您調用函數的對象的指針。

4

這是依賴於實現 - 它沒有在標準中指定。然而,你是對的,非虛擬成員函數(甚至是第一個之後的虛擬函數)不會影響類的大小。

這是因爲如果每個類的實例都有指向所有函數的指針,它會佔用大量內存。他們爲什麼會這樣?在運行時,對象知道它是什麼類型,並且可以調用相應的函數。同一個函數在不同實例中是相同的,所有不同的是它在其上運行的對象,它作爲參數在引擎蓋下傳遞。

1

因爲函數狀態會留在堆棧中,並且在函數進入/退出時被創建/刪除。

在對象的大小中,只有那些有助於存儲對象狀態的成員。函數只是一段代碼,它從一個給定的點開始,並不依賴於它引用的特定對象實例。

認爲

A a1, a2; 

a1.a和a2.a是不同的,但a1.display()和a2.dispaly()是相同的功能代碼 (認爲int A::display())作爲int display(A* this)

3

函數/方法存儲爲代碼,而不是數據。就像一個可執行文件存儲爲單個文件一樣,並且可能會多次啓動 - 並且它的多個實例將具有不同的數據。同樣,一個函數是可執行代碼,並且傳遞給它的數據可能不同(如同一個文字處理軟件的不同文檔)。

可執行代碼將不會有任何sizeof,因爲它們在程序運行時不佔用堆棧或堆上的空間。它存儲在可執行映像中,並在啓動程序時由OS加載一次。

2

除了爲實現虛擬函數和虛擬繼承而引入的隱藏數據成員外,實例大小完全由類的數據成員和基類決定。C++: Under the Hood(1994)如果你想知道更多。

2

成員函數是進程文本段的一部分,對象是進程數據段的一部分。因爲對象只是數據,所以它通過添加一個類的所有數據成員的大小來計算大小。成員函數對於所有對象都是通用的,它只是由特定對象指針的第一個參數(稱爲this指針)不同而定,它作爲隱藏指針傳遞給類的每個成員函數。