Ukazatelé na členy
Deklarace ukazatelů na členy jsou zvláštní případy deklarací ukazatelů. Deklarují se pomocí následující sekvence:
specifikátory třídy storage optcv-kvalifikátory opt type-specifierms-modifieroptqualified-name
::*
cv-kvalifikátoryoptidentifierpm-initializer opt;
Specifikátor deklarace:
Volitelný specifikátor třídy úložiště.
Volitelné
const
avolatile
specifikátory.Specifikátor typu: název typu. Jedná se o typ člena, na který se má odkazovat, nikoli na třídu.
Deklarátor:
Volitelný modifikátor specifický pro Microsoft. Další informace naleznete v tématu Modifikátory specifické pro Microsoft.
Kvalifikovaný název třídy obsahující členy, na které mají být odkazovat.
Operátor
::
.Operátor
*
.Volitelné
const
avolatile
specifikátory.Identifikátor pojmenování ukazatele na člen.
Volitelný inicializátor ukazatele na člen:
Operátor
=
.Operátor
&
.Kvalifikovaný název třídy.
Operátor
::
.Název nestatického člena třídy příslušného typu.
Stejně jako vždy je povoleno více deklarátorů (a všech přidružených inicializátorů) v jedné deklaraci. Ukazatel na člen nesmí odkazovat na statický člen třídy, člen referenčního typu nebo void
.
Ukazatel na člen třídy se liší od normálního ukazatele: obsahuje informace o typu pro typ členu i pro třídu, do které člen patří. Normální ukazatel identifikuje (má adresu) pouze jeden objekt v paměti. Ukazatel na člen třídy identifikuje člena v libovolné instanci třídy. Následující příklad deklaruje třídu Window
a některé ukazatele na data členů.
// pointers_to_members1.cpp
class Window
{
public:
Window(); // Default constructor.
Window( int x1, int y1, // Constructor specifying
int x2, int y2 ); // Window size.
bool SetCaption( const char *szTitle ); // Set window caption.
const char *GetCaption(); // Get window caption.
char *szWinCaption; // Window caption.
};
// Declare a pointer to the data member szWinCaption.
char * Window::* pwCaption = &Window::szWinCaption;
int main()
{
}
V předchozím příkladu pwCaption
je ukazatel na libovolný člen třídy Window
, který je typu char*
. Typ pwCaption
je char * Window::*
. Další fragment kódu deklaruje ukazatele na SetCaption
členské funkce a GetCaption
funkce.
const char * (Window::* pfnwGC)() = &Window::GetCaption;
bool (Window::* pfnwSC)( const char * ) = &Window::SetCaption;
Ukazatele pfnwGC
a ukazují na GetCaption
třídu a Window
SetCaption
pfnwSC
v uvedeném pořadí. Kód zkopíruje informace do okna popis přímo pomocí ukazatele na členpwCaption
:
Window wMainWindow;
Window *pwChildWindow = new Window;
char *szUntitled = "Untitled - ";
int cUntitledLen = strlen( szUntitled );
strcpy_s( wMainWindow.*pwCaption, cUntitledLen, szUntitled );
(wMainWindow.*pwCaption)[cUntitledLen - 1] = '1'; // same as
// wMainWindow.SzWinCaption [cUntitledLen - 1] = '1';
strcpy_s( pwChildWindow->*pwCaption, cUntitledLen, szUntitled );
(pwChildWindow->*pwCaption)[cUntitledLen - 1] = '2'; // same as
// pwChildWindow->szWinCaption[cUntitledLen - 1] = '2';
Rozdíl mezi operátory .*
a ->*
operátory (operátory ukazatele na člena) spočívá v tom, že .*
operátor vybere členy vzhledem k objektu nebo objektu, zatímco ->*
operátor vybere členy ukazatelem. Další informace o těchto operátorech naleznete v tématu Výrazy s operátory ukazatele na člena.
Výsledkem operátorů ukazatele na člen je typ členu. V tomto případě je to char *
.
Následující fragment kódu vyvolá členské funkce GetCaption
a SetCaption
pomocí ukazatelů na členy:
// Allocate a buffer.
enum {
sizeOfBuffer = 100
};
char szCaptionBase[sizeOfBuffer];
// Copy the main window caption into the buffer
// and append " [View 1]".
strcpy_s( szCaptionBase, sizeOfBuffer, (wMainWindow.*pfnwGC)() );
strcat_s( szCaptionBase, sizeOfBuffer, " [View 1]" );
// Set the child window's caption.
(pwChildWindow->*pfnwSC)( szCaptionBase );
Omezení ukazatelů členů
Adresa statického členu není ukazatel na člena. Je to běžný ukazatel na jednu instanci statického členu. Pro všechny objekty dané třídy existuje pouze jedna instance statického členu. To znamená, že můžete použít běžné operátory adres (&) a dereference (*).
Ukazatelé na členy a virtuální funkce
Vyvolání virtuální funkce prostřednictvím funkce ukazatele na člen funguje stejně, jako kdyby byla funkce volána přímo. Správná funkce se vyhledá v tabulce v a vyvolá se.
Klíč k fungování virtuálních funkcí je jako vždy volá prostřednictvím ukazatele na základní třídu. (Další informace o virtuálních funkcích najdete v tématu Virtuální funkce.)
Následující kód ukazuje, jak zavolat virtuální funkci pomocí funkce ukazatele na člen:
// virtual_functions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Print();
};
void (Base::* bfnPrint)() = &Base::Print;
void Base::Print()
{
cout << "Print function for class Base" << endl;
}
class Derived : public Base
{
public:
void Print(); // Print is still a virtual function.
};
void Derived::Print()
{
cout << "Print function for class Derived" << endl;
}
int main()
{
Base *bPtr;
Base bObject;
Derived dObject;
bPtr = &bObject; // Set pointer to address of bObject.
(bPtr->*bfnPrint)();
bPtr = &dObject; // Set pointer to address of dObject.
(bPtr->*bfnPrint)();
}
// Output:
// Print function for class Base
// Print function for class Derived
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro