2011-11-19 93 views
3

所以我一直以爲當你做ObjectA.field1之類的東西時,ObjectA就像堆棧中的任何值一樣,你基本上訪問它的字段。現在我正在瀏覽關於OOP語言的類,並且意識到當你做ObjectA.field1時,實際發生的是HEAP(ObjectA的地址)(field1),它返回field1的值。這讓我有點困惑。任何人都可以告訴爲什麼有一個查詢正在進行,雖然我們已經有了對象的價值?希望我能解釋..對象的內部表示

+2

我不清楚'HEAP'應該做什麼。 – bames53

+0

HEAP接收地址並返回對象 – Cemre

+0

因此HEAP(ObjectA的地址)返回ObjectA。那麼ObjectA(field1)做什麼? – bames53

回答

7

物體並不是那麼神奇。從本質上講,一個對象只是由其所有成員的線性集合組成,在成員周圍沒有指定數量的填充。佈局的角度來看,一個C++類基本上像一個C結構:

struct Foo { 
    int a; 
    char b; 
    std::string s; 

    static long q; 

    void bar() { print(s); log(a); } 
    static void car() { } 
} 

忽略成員函數和靜力學現在,這可能被佈局是這樣的:

+= class Foo =+ 
+-------------+ ---\ <--- Foo * p 
| int  |  s 
+-------------+  i 
| char  |  z 
+-------------+  e 
| <padding> |  o 
+-------------+  f 
| std::string | (F 
+-------------+  o 
| <padding> |  o) 
+-------------+ ---/ 

類的每個對象Foo是像這樣存儲在內存中。我們需要的唯一額外數據是靜態成員,成員函數和靜態成員函數。

靜態成員只是全局變量。因此,我們只有一個全局變量:

+== static__Foo__q ==+ 
+--------------------+ 
| long int   | 
+--------------------+ 

接下來,靜態成員函數只是普通的,無功能:

void static__Foo__car() { } 

最後,成員函數:這些人基本上也只是普通的功能,雖然有一個額外的參數可以讓他們找到實例成員:

void member__Foo__bar(Foo * p) { print(p->s); log(p->a); } 

唯一重要的區別是你不能獲得一個普通的自由函數指針給成員函數,因爲實現函數的實際名稱沒有公開。參考Foo::bar()的唯一方法是通過指向成員函數void (Foo::*ptfm)() = &Foo::bar。成員對象有點簡單:你可以獲得一個普通的指針,比如Foo x; int * p = &x.a;,但是你也可以形成一個指向成員的指針:int Foo::*ptm = &Foo::a;

然後,如果我們有對象Foo x, y, z;,我們可以使用雙實例指針Foo * pi = &x;和成員指針int &Foo::* ptm = &Foo::avoid (Foo::*ptfm)() = &Foo::bar訪問給定實例的相關成員:整數pi->*ptm,和函數調用(pi->*ptfm)(),分別。 (是的,->*是一個操作符。)

(函數指針的一個免費版本不能存在,因爲多態(虛擬)函數比簡單的固定函數指針需要更復雜的調度機制。)

+0

+1對於ASCII藝術。我確定知道它需要很多努力:) –

+0

我修復了關於成員*對象的最後部分*:你可以同時擁有一個指向成員對象的直接空閒指針('&x.a '),*也是*實例指針/成員指針對,'(&x,&Foo :: a)'。 –

+0

你還可以解釋爲什麼'char'和'std :: string'對象之間需要填充? –

3

那麼一些ObjectA的一些ClassA計算機有field1有含ObjectA,它知道(靜態)的偏移量(以字節爲單位)field1的存儲區的地址( ClassA),因此它可以通過將該偏移量添加到ObjectA的地址來檢索field1

+0

因此,當我們取消引用一個指針來獲取對象的值,或者我們得到該對象的「真實地址」時?感謝回覆 – Cemre

+0

指針是對象的地址。通常,你解除引用正如我所解釋的那樣,它具有偏移量。 –

+0

在執行ObjectA.field1時,不會在C++語言級別取消引用指針。 ObjectA是一個左值,它由內存中的一系列字節組成。爲了訪問field1,程序具有關於對象的哪些字節包括其每個字段的信息。所以ObjectA.field1是一個表達式,其結果是一個由組成子對象field1的ObjectA的字節組成的左值。 – bames53