¿Cuáles son los operadores Pointer-to-Member->*y.*En C++?
operators operator-arrow-star (6)
Sí, he visto esta pregunta y estas preguntas frecuentes (enlace incorrecto) estas preguntas frecuentes , pero sigo sin entender qué significan ->*
y .*
En C ++.
Esas páginas proporcionan información sobre los operadores (como la sobrecarga), pero no parecen explicar bien lo que son .
¿Qué son ->*
y .*
En C ++, y cuándo es necesario usarlos en comparación con ->
y .
?
Cuando tienes un puntero normal (a un objeto o un tipo básico), usarías *
para desreferenciarlo:
int a;
int* b = a;
*b = 5; // we use *b to dereference b, to access the thing it points to
Conceptualmente, estamos haciendo lo mismo con un puntero de función miembro:
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 ();
Espero que eso ayude a explicar el concepto. Estamos efectivamente desreferenciando nuestro puntero a la función miembro. Es un poco más complicado que eso: no es un puntero absoluto para una función en la memoria, sino solo un desplazamiento, que se aplica a foo
o p
arriba. Pero conceptualmente, estamos desreferenciando, al igual que eliminaríamos un puntero de objeto normal.
EDITAR: Por cierto, se vuelve extraño para los punteros de funciones de miembros virtuales .
Para las variables miembro:
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;
}
Las funciones de los miembros son casi las mismas.
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 ();
}
En resumen: Usas ->
y .
si sabe a qué miembro desea acceder. Y usa ->*
y .*
Si no sabe a qué miembro desea acceder.
Ejemplo con una simple lista intrusiva
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;
};
Espero que este ejemplo aclare las cosas para ti
//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();
Ahora, no puede usar x.somePointer()
, ni px->somePointer()
porque no hay ningún miembro de esa clase en la clase X. Para eso se usa la sintaxis de llamada especial de puntero a la función miembro ... solo pruebe algunos ejemplos ,te acostumbrarás
Los llamados "punteros" para los miembros en C ++ son más como compensaciones, internamente. Necesita tanto un "puntero" miembro y un objeto para hacer referencia al miembro en el objeto. Pero los "punteros" de miembro se usan con sintaxis de puntero, de ahí el nombre.
Hay dos formas en que puede tener un objeto a mano: tiene una referencia al objeto o tiene un puntero al objeto.
Para la referencia, use .*
Para combinarlo con un puntero de miembro, y para el puntero, use ->*
para combinarlo con un puntero de miembro.
Sin embargo, como regla general, no use punteros de miembro si puede evitarlo.
Obedecen reglas bastante contrarias a la intuición, y hacen posible eludir el acceso protected
sin un casting explícito, es decir, inadvertidamente ...
Saludos y hth.,
No puede desreferenciar el puntero a los miembros como punteros normales, porque las funciones miembro requieren this
puntero, y usted tiene que pasarlo de alguna manera. Por lo tanto, debe utilizar estos dos operadores, con el objeto en un lado y el puntero en otro, por ejemplo, (object.*ptr)()
.
Considere el uso de function
y bind
( std::
o boost::
, dependiendo de si escribe C ++ 03 o 0x) en lugar de aquellos.