2011-07-05 46 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。但从概念上讲,我们正在取消引用它,就像我们将引用一个普通的对象指针一样。

相关问题