Zugriffsoperatoren zwischen Zeigern .*und Mitgliedern: und->*
Die Zugriffsoperatoren Zeiger auf Mitglied.* und ->*dienen zum Dereferenzieren eines Zeigers auf ein Mitglied in Kombination mit einem Objekt bzw. einem Zeiger auf ein Objekt . Diese Beschreibung gilt sowohl für Zeiger auf Datenelemente als auch für Zeiger auf Elementfunktionen .
Betrachten Sie zum Beispiel die Klasse Foo:
struct Foo {
int i;
void f();
};
Wenn Sie einen Elementzeiger deklarieren iPtr, auf ein intDatenelement von Foo:
int Foo::* iPtr;
Sie können diesen Elementzeiger iPtrso initialisieren , dass er auf das Foo::iElement zeigt:
iPtr = &Foo::i;
Um diesen Zeiger zu dereferenzieren, müssen Sie ihn in Verbindung mit einem FooObjekt verwenden.
Betrachten Sie nun das Objekt foound den Zeiger auf das Objekt fooPtr:
Foo foo;
Foo* fooPtr = &foo;
Dann können Sie iPtrin Kombination mit foooder dereferenzieren fooPtr:
foo.*iPtr = 0;
fooPtr->*iPtr = 0;
Analog können Sie .*und ->*mit Zeigern auf Funktionselemente verwenden . Beachten Sie jedoch, dass Sie sie in Klammern setzen müssen, da der Funktionsaufrufoperator , dh() hat eine höhere Priorität als die beiden .*und ->*:
void (Foo::*memFuncPtr)() = &Foo::f;
(foo.*memFuncPtr)();
(fooPtr->*memFuncPtr)();
Fazit: Sie benötigen ein Objekt, um einen Zeiger auf ein Element zu dereferenzieren, und welches Sie entweder .*oder ->*zum Dereferenzieren des Zeigers auf das Element verwenden, hängt davon ab, ob dieses benötigte Objekt direkt oder über einen Objektzeiger bereitgestellt wird.
C ++ 17 - Verwenden Sie std::invoke()stattdessen
Die Verwendung beider Operatoren kann seit C ++ 17 durch die std::invokeFunktionsvorlage ersetzt werden. std::invokeBietet eine einheitliche Möglichkeit zum Dereferenzieren von Elementzeigern, unabhängig davon, ob Sie sie in Kombination mit einem Objekt oder einem Objektzeiger verwenden , und unabhängig davon, ob der Zeiger auf Element einem Zeiger auf Datenelement oder Zeiger auf Elementfunktion entspricht :
std::invoke(iPtr, foo) = 0;
std::invoke(iPtr, fooPtr) = 0;
std::invoke(memFuncPtr, foo);
std::invoke(memFuncPtr, fooPtr);
Diese einheitliche Syntax entspricht der normalen Funktionsaufrufsyntax und erleichtert möglicherweise das Schreiben von generischem Code.