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 int
Datenelement von Foo
:
int Foo::* iPtr;
Sie können diesen Elementzeiger iPtr
so initialisieren , dass er auf das Foo::i
Element zeigt:
iPtr = &Foo::i;
Um diesen Zeiger zu dereferenzieren, müssen Sie ihn in Verbindung mit einem Foo
Objekt verwenden.
Betrachten Sie nun das Objekt foo
und den Zeiger auf das Objekt fooPtr
:
Foo foo;
Foo* fooPtr = &foo;
Dann können Sie iPtr
in Kombination mit foo
oder 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::invoke
Funktionsvorlage ersetzt werden. std::invoke
Bietet 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.