2011-07-05 42 views
47

是的,我見過this question this FAQ(錯誤的鏈接) this FAQ,但我仍然不明白->*.*意味着C++。
那些頁面提供的信息運營商(如超載),但似乎並沒有很好地解釋他們什麼是指針 - 成員 - > *和。*運算符在C++中?

什麼是->*.*在C++中,和->.相比,您何時需要使用它們?

+3

我認爲[這個FAQ](http://www.parashift.com/c++-faq-lite/pointers-to-members.html)對它進行了相當好的解釋。 –

+0

@Rob:我不相信我發佈了錯誤的鏈接。 X___X這是我打算髮布的,而不是MSDN! - 我看過它,但是我對它不瞭解太多。他們所說的只是「類型不同」,但我發現那種混淆...... – Mehrdad

回答

50

我希望這個例子清楚你的東西

//we have a class 
struct X 
{ 
    void f() {} 
    void g() {} 
}; 

typedef void (X::*pointer)(); 
//ok, let's take a pointer and assign f to it. 
pointer somePointer = &X::f; 
//now I want to call somePointer. But for that, I need an object 
X x; 
//now I call the member function on x like this 
(x.*somePointer)(); //will call x.f() 
//now, suppose x is not an object but a pointer to object 
X* px = new X; 
//I want to call the memfun pointer on px. I use ->* 
(px ->* somePointer)(); //will call px->f(); 

現在,你不能用x.somePointer(),或px->somePointer()因爲在十類沒有這樣的成員對於特殊的成員函數指針調用語法使用...只是自己嘗試幾個例子,你會習慣它

+2

添加**所需的**額外大括號來補償運算符優先級。 –

+2

@阿門:哦,我現在看到發生了什麼......我從來沒有見過或需要這樣的事情。這很酷(+1),但我現在的問題是:「指針」與普通函數指針有什麼不同,它需要不同的語法? (例如它是否更大?) – Mehrdad

+0

@Mehrdad:關鍵是要調用普通函數,只需提供參數。但是在非靜態成員函數的情況下,你還需要一個你想調用函數的對象。因此,新的語法。 –

10

簡而言之:如果你知道你想訪問的成員,你使用->.。如果您使用->*.*,並且不知道知道您想訪問哪個成員。

實施例用簡單的侵入列表

template<typename ItemType> 
struct List { 
    List(ItemType *head, ItemType * ItemType::*nextMemPointer) 
    :m_head(head), m_nextMemPointer(nextMemPointer) { } 

    void addHead(ItemType *item) { 
    (item ->* m_nextMemPointer) = m_head; 
    m_head = item; 
    } 

private: 
    ItemType *m_head; 

    // this stores the member pointer denoting the 
    // "next" pointer of an item 
    ItemType * ItemType::*m_nextMemPointer; 
}; 
+4

第一句話+1,但我的生活中從來沒有*我*不知道我想訪問哪個成員,哈哈。 :) – Mehrdad

6

所謂的「指針」在C++成員更像偏移,在內部。您需要這樣一個成員「指針」和一個對象來引用對象中的成員。但成員「指針」用於指針語法,因此名稱。

有兩種方法可以使對象在手邊:您有對象的引用,或者您有指向對象的指針。

爲了便於參考,請使用.*將其與成員指針結合使用,對於指針,請使用->*將其與成員指針組合使用。

但是,通常情況下,如果可以避免使用成員指針,則不要使用成員指針。

他們服從非常違反直覺的規則,並且它們可以規避protected訪問,而不需要任何明確的轉換,也就是不經意間&hellip;

乾杯&心連心,

+0

+1爲解釋它沒有代碼。 :)問題:爲什麼我們不能像普通函數那樣獲取函數的地址?是指向一個成員函數的指針與指向其他某個函數的指針不同? (例如它是否更大?) – Mehrdad

+1

@Mehrdad:如果您可以有一個指向僅限於非虛擬成員函數的成員函數的指針,那麼它確實可能只是地址。但是,虛擬或不是不是成員函數指針類型的一部分。因此,它的表示需要包含一些關於當前值是否指向虛擬函數的信息,如果是虛擬的,則針對基於vtable的實現信息來確定指針類型與類的vtable中的偏移量有關的信息。 –

4

不能解引用指針成員正常的指針 - 因爲成員函數需要this指針,你必須以某種方式通過。所以,你需要使用這兩個操作符,一邊是對象,另一邊是指針,例如(object.*ptr)()。儘管如此,考慮使用functionbindstd::boost::,取決於您是否編寫C++ 03或0x)而不是這些。

+0

我認爲這可能是這裏最好的解釋。 – Marcin

18

編輯:順便說一句,它變得很奇怪的virtual member functions pointers

成員變量:

struct Foo { 
    int a; 
    int b; 
}; 


int main() 
{ 
    Foo foo; 
    int (Foo :: * ptr); 

    ptr = & Foo :: a; 
    foo .*ptr = 123; // foo.a = 123; 

    ptr = & Foo :: b; 
    foo .*ptr = 234; // foo.b = 234; 
} 

成員函數幾乎是一樣的。

struct Foo { 
    int a(); 
    int b(); 
}; 


int main() 
{ 
    Foo foo; 
    int (Foo :: * ptr)(); 

    ptr = & Foo :: a; 
    (foo .*ptr)(); // foo.a(); 

    ptr = & Foo :: b; 
    (foo .*ptr)(); // foo.b(); 
} 
+2

+1表示該語法適用於所有成員,而不僅僅是成員函數。儘管我發現指向成員變量的指針很少被使用,儘管它們有許多相當有趣的潛在應用。 –

5

當你有一個正常的指針(對象或基本類型),你可以使用*取消對它的引用:

int a; 
int* b = a; 
*b = 5;  // we use *b to dereference b, to access the thing it points to 

從概念上講,我們正在做同樣的事情成員函數指針:

class SomeClass 
{ 
    public: void func() {} 
}; 

// typedefs make function pointers much easier. 
// this is a pointer to a member function of SomeClass, which takes no parameters and returns void 
typedef void (SomeClass::*memfunc)(); 

memfunc myPointer = &SomeClass::func; 

SomeClass foo; 

// to call func(), we could do: 
foo.func(); 

// to call func() using our pointer, we need to dereference the pointer: 
foo.*myPointer(); 
// this is conceptually just: foo . *myPointer (); 


// likewise with a pointer to the object itself: 
SomeClass* p = new SomeClass; 

// normal call func() 
p->func(); 

// calling func() by dereferencing our pointer: 
p->*myPointer(); 
// this is conceptually just: p -> *myPointer (); 

我希望能幫助解釋這個概念。我們正在有效地解除引用我們的成員函數的指針。它比這更復雜一點 - 它不是指向內存函數的絕對指針,而是一個偏移量,它應用於上面的foop。但從概念上講,我們正在取消引用它,就像我們將引用一個普通的對象指針一樣。

相關問題