2011-03-05 45 views
4

以下是布魯斯Eckel的Thinking in C++標題下一個段落(第1卷,第2版,第11章)「成員指針」:指針從布魯斯Eckel的思考成員在C++

...指針需求一個地址,但課堂內沒有「地址」;選擇班級成員意味着抵消該班級。您不能生成實際的地址,直到您將該偏移量與特定對象的起始地址相結合。指向成員的指針語法要求您在取消引用成員指針的同時選擇一個對象。

這句話是什麼意思?我試圖做這樣的事情:

&(objectname.member_variable) 

我得到一個實際地址,像0x22f14,但這種補償裝置有多遠從起始地址?

回答

6

我認爲&(foo.bar)只是一個指向變量的常規指針。通過說「指向成員」我們的意思是像&(FooClass::bar),沒有specyfying任何對象!注意,這個值實際上可以在編譯時計算出來,並且可以用於例如在模板中。

成員指針有很奇怪的語法。

嘗試運行下面的代碼:

#include <stdio.h> 

class FooClass { 
    public: 
    int bar; 
    int bar2; 
    FooClass() : bar(0), bar2(0) {} 
}; 

int main() { 

    //Showing what member pointers actually hold: 
    int FooClass::* barPtr=&FooClass::bar; 
    int FooClass::* bar2Ptr=&FooClass::bar2; 
    printf("barPtr=%p\nbar2Ptr=%p\n",barPtr,bar2Ptr); 

    //Showing how to use them: 
    FooClass foo; 
    foo.*bar2Ptr=42; 
    printf("foo={%d,%d}\n",foo.bar,foo.bar2); 
} 

你會得到輸出:

barPtr=0x0 
bar2Ptr=0x4 
foo={0,42} 

正如你可以看到,這兩個值持有從上課開始的成員偏移。即使你不知道你正在工作的是哪個對象,他們也可以被計算出來。

但是,如果您想取消引用它們,則必須提供一個對象 - 這就是.*運算符所要做的。

+0

你不能在成員指針上使用'printf(...%p ...)',他們是完全不同的動物... – Lindydancer

+0

你可能通常不想在生產代碼中這樣做,但你可以用於測試目的。它們通常具有相同的尺寸(雖然不能保證)。你可能不希望爲通常較大的成員函數指針這樣做,但這是另一回事。 – CygnusX1

0

是的,在這種情況下,術語偏移意味着特定構件多遠存儲在存儲器中從該類的第一構件(其爲物體位置)。

作爲結果得到的值是成員* member_variable *的內存位置。只是爲了可視化目的,如果你想知道字節偏移量,你可以這樣做:

std::cout << reinterpret_cast<char *>(&(objectname.member_variable)) - reinterpret_cast<char *>(&objectname);