2011-09-30 46 views
0
class classWithNoVirtualFunction 
{ 
    public: 
     int a; 
     void x() 
     { 
      char c; 
      c = 'a'; 
     } 
}; 

class classWithOneVirtualFunction 
{ 
public: 
    int   a; 
    virtual void x() {} 
}; 

class classWithTwoVirtualFunctions 
{ 
public: 
    int   a; 
    virtual void x() {} 
    virtual void y() {} 
}; 

int main() 
{ 
    cout << "\nclassWithNoVirtualFunction's size: " << sizeof (classWithNoVirtualFunction);  
    cout << "\nclassWithOneVirtualFunction's size: " << sizeof (classWithOneVirtualFunction); 
    cout << "\nclassWithTwoVirtualFunctions's size: " << sizeof (classWithTwoVirtualFunctions); 

    cout << "\nvoid*'s size : " << sizeof (void*); 
} 

W.R.T上面的代碼,在C++思考說:爲什麼只有虛擬功能纔會影響課堂的規模?

該實施例所需的至少一個數據成員。如果沒有 數據成員,則C++編譯器將強制將對象設置爲非零大小,因爲每個對象都必須具有不同的地址。如果你想象索引到一個零大小的對象數組中,你將會理解 。將一個「虛擬」成員插入對象中,否則該對象將爲零。

我的問題:現在,我無法理解什麼& &如何到底會發生,如果我們有任何成員和虛擬函數的類。請用一些編程示例來解釋。

+0

我不明白這是怎麼解釋的*編程示例*超出你已經添加(刪除'int')。順便說一句,該程序的預期輸出將是(1,x,x,x),其中x是體系結構中指針的大小(對於32/64位體系結構,通常爲4/8)。 –

+1

@DavidRodríguez-dribeas嚴格地說,沒有要求第一個輸出是1,只是它不是0.在一個尋址的機器上(Unisys主機),我希望它是一個字的大小,並且所有值是相同的。嚴格地說,也沒有要求剩餘值也是相同的;我在硬件上使用了一個'void *'大於'vptr'所需的硬件。 (但那是在C++的日子之前;我不認爲任何這樣的野獸仍然存在。) –

回答

5

只要一個類至少包含一個虛擬函數,編譯器就需要將RunTime類型信息添加到每個對象。該實現通常會將一個指針添加到每個指向由編譯器定義且對用戶隱藏的結構的對象,並指向type_info對象和用於動態分配函數的vtable

在沒有非靜態數據成員和至少一個虛函數的類的情況下,每個對象的大小是每個對象的RTTI信息(一個指針)的大小,並且因爲這是非 - 零,編譯器不會添加額外的空間。引言所說的是sizeof(T) != 0適用於任何和所有類型的T,而具有動態功能的類型可以滿足這一要求。只有具有零大小的類型,編譯器纔會強制將對象設置爲char大。

+0

什麼是'RunTime Type Information'?我不明白'每個對象的大小是每個對象RTTI信息的大小(一個指針),並且因爲它不爲零,所以編譯器不會添加額外的空間。 「我不明白你的答案。 –

+0

RTTI是運行時間類型信息包括類型信息和用於功能調度的虛擬表。對於沒有虛函數的對象,對象的typeid(通過指針或引用訪問)是指針或引用的靜態類型:'nonvirtual * p = f(); typeid(* p);'在編譯時將被解析爲'typeid(nonvirtual)',但是如果類型'virt'具有虛函數,那麼'virt * p = f(); typeid(* p);'將爲您提供最多派生對象的類型信息,可能是'virt'或從它派生的對象。 –

+0

RTTI的第二面是虛擬表,它是調度機制的常見實現,基本上是一個包含對象中所有虛擬函數的函數指針的表。層次結構中的'base'子對象將包含一個指向一個這樣的表('vptr')的指針,層次中的每個'derived'類型將覆蓋'vptr'來引用不同的'vtable',它們持有指向*每個級別的虛擬功能的最終覆蓋*。爲了提高效率,'type_info'和'vtable'綁定在一個結構中,並且每個對象都包含一個指針。 –

0

C++標準沒有定義類的完整佈局。這取決於編譯器供應商。但是C++標準確實提供了一些保證。例如,完整對象的大小總是大於零。這條規則的原因是由您在C++中引用的文字暗示的。一個簡單類的虛函數是通常是實現的附加隱藏指針成員標識對象的動態類型,以便可以調用對象的動態類型的正確功能。由於這個額外的隱藏成員增加了類的大小,因此編譯器不需要在其中放置任何填充以使該類具有非零大小。

但是,這些主要是實施細節,你不應該擔心太多。只要你只依靠C++標準制定的保證,你應該沒問題。

相關問題