Каковы операторы Pointer-to-Member → * и. * В С++?
Да, я видел этот вопрос и этот FAQ (неверная ссылка) этот FAQ, но я до сих пор не понимаю, что означают ->*
и .*
в С++.
Эти страницы предоставляют информацию об операторах (например, перегрузку), но, похоже, не объясняют, каковы они.
Что такое ->*
и .*
в С++, и когда вам нужно использовать их по сравнению с ->
и .
?
Ответы
Ответ 1
Я надеюсь, что этот пример очистит вас для вас.
//we have a class
struct X
{
void f() {}
void g() {}
};
typedef void (X::*pointer)();
//ok, let 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()
, потому что в классе X нет такого члена. Для этого используется специальный синтаксис вызова указателя функции-члена... просто попробуйте несколько примеров самостоятельно, вы привыкнуть к нему
Ответ 2
EDIT: Кстати, это странно для указателей функций виртуальных членов.
Для переменных-членов:
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 ();
}
Ответ 3
Вкратце: вы используете ->
и .
, если знаете, к кому вы хотите получить доступ. И вы используете ->*
и .*
, если вы не знаете, к кому вы хотите получить доступ.
Пример с простым интрузивным списком
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
Так называемые "указатели" для членов на С++ больше похожи на смещения внутри. Вам нужен и такой "указатель" члена, и объект, чтобы ссылаться на элемент в объекте. Но члены "указатели" используются с синтаксисом указателя, отсюда и название.
Существует два способа иметь объект под рукой: у вас есть ссылка на объект или указатель на объект.
Для ссылки используйте .*
, чтобы объединить его с указателем-членом, а для указателя используйте ->*
, чтобы объединить его с указателем-членом.
Однако, как правило, не используйте указатели-члены, если вы можете избежать этого.
Они подчиняются довольно противоречивым правилам, и они позволяют обойти protected
доступ без какого-либо явного литья, то есть непреднамеренно & hellip;
Приветствия и hth.,
Ответ 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 ();
Я надеюсь, что это поможет объяснить концепцию. Мы фактически разыскиваем наш указатель на функцию-член. Это немного сложнее, чем это - это не абсолютный указатель на функцию в памяти, а просто смещение, которое применяется к foo
или p
выше. Но концептуально мы разыгрываем его, так же, как мы бы разыменовали обычный указатель объекта.
Ответ 6
Вы не можете разыменовывать указатели на члены как обычные указатели, потому что для функций-членов требуется указатель this
, и вы должны каким-то образом передать его. Таким образом, вам нужно использовать эти два оператора, с объектом с одной стороны, и указатель на другом, например. (object.*ptr)()
.
Рассмотрим вместо function
и bind
(std::
или boost::
, в зависимости от того, пишите ли вы С++ 03 или 0x).