2015-10-06 67 views
0

爲了在這裏省略一些重複並縮小問題的範圍,我將很快涵蓋我相信我理解的內容。一個班級如何知道其成員的大小?

一個類是一個指向不同大小變量的指針,稱爲成員。如果成員大小不同,則它們將被分配到最大成員的大小相同的空間。

所以在內存中他們都是相同的大小,因此我的問題:一個班級如何知道其成員的大小?

例子:

class foo 
{ 
    short a = 99; 
    int b = 88; 
}; 

int main() 
{ 
    foo f; 

    for (int i = 0; i < sizeof(f); i++) 
     cout << (int)((char*)&f)[i] << " "; 

    return 0; 
} 

// Output: 
// 99 0 -1 70 88 0 0 0 
// 
// where -1 and 70 are random bytes in memory 

所以我稱讚那些主要問題誰不明白:如何˚F讀取構件當知道怎麼回事(99 0)而不是int(99 0 -1 70)?

+5

一個類不是一個指針,下面沒有任何意義。你似乎在混淆階級和工會。 – Mat

+0

停止鑄造。如果你知道自己在做什麼,那就很棘手,而你顯然不知道。你所做的是未定義的行爲,你不能從輸出中推斷出任何東西。 – MSalters

回答

1

這對編譯器任務,這就是爲什麼類必須在類似這種情況下,一個完整的類型,這是編譯器需要這個:

struct foo { 
    short f; 
    int b; 
}; 

...或相似。當類型完成時,編譯器可以決定類型的大小,字段的偏移量以及在某些情況下需要知道的其他事情。

如果沒有一個完整的類型定義,將不能夠:

  1. 接受foo類型(即foo f;聲明)的變量聲明。
  2. 接受sizeof(foo)表達式
  3. 創建指向成員的指針。
  4. ...等等。

既然你不能聲明變量f沒有完整的類型,你將無法獲得它的大小或訪問它的成員。

如果在另一邊使用不完整的類型。這是編譯器只看到:

struct foo; 

那麼編譯器不能做任何事情,需要一個完整的類型,但它可以例如具有指針foo,但不能看裏面,它分配或做指針算法。

+0

感謝您提供完整且詳細的答案,並附有清晰的示例。我明白。 –

2

該類不需要知道,您的編譯器會。

如果成員的大小不同,它們都被分配了與最大成員大小相同的空間。

這根本不是真的。試想一個有兩個成員的課程,首先是一個20個雙打的大結構,然後是一個單個字符。

0

你有一些誤解,但爲了更好的理解你可能會嘗試的一件事是在一些簡單的結構上使用來自<stddef.h>offsetof(typename, membername)宏。也許嘗試打印offsetof(foo, a),offsetof(foo, b),(uintptr_t)&f(uintptr_t)&f.b,看看編譯器如何找到f.b給定的地址爲f。在類方法中,f被命名爲this。 (另外他們也有一個指向他們虛擬函數的指針表,當你調用其中一個時,你真的調用了該表中的第一個,第二個或第三個函數)。單繼承的工作方式是,所有基類的成員和方法首先出現在相同的偏移處,派生類中。多重繼承的工作方式很複雜。