Pointeurs vers membres
Les déclarations de pointeurs vers des membres sont des cas spéciaux de déclarations de pointeur. Ils sont déclarés à l’aide de la séquence suivante :
storage-class-specifiersoptcv-qualifiersopttype-specifierms-modificateuroptqualified-name
::*
cv-qualifiersoptidentifierpm-initializer opt;
Spécificateur de déclaration :
Spécificateur de classe de stockage facultatif.
Spécificateurs et
volatile
facultatifsconst
.Spécificateur de type : nom d'un type. Il s’agit du type du membre auquel faire référence, et non de la classe.
Déclarateur :
Modificateur spécifique à Microsoft facultatif. Pour plus d’informations, consultez Modificateurs spécifiques à Microsoft.
Nom qualifié de la classe contenant les membres vers lesquels pointer.
opérateur
::
,opérateur
*
,Spécificateurs et
volatile
facultatifsconst
.Identificateur nommant le pointeur vers le membre.
Initialiseur de pointeur à membre facultatif :
opérateur
=
,opérateur
&
,Nom qualifié de la classe.
opérateur
::
,Nom d’un membre non statique de la classe du type approprié.
Comme toujours, les déclarateurs multiples (et tout initialiseur associé) sont autorisés dans une même déclaration. Un pointeur vers un membre peut ne pas pointer vers un membre statique de la classe, un membre de type référence ou void
.
Un pointeur vers un membre d’une classe diffère d’un pointeur normal : il contient à la fois des informations de type pour le type du membre et pour la classe à laquelle appartient le membre. Un pointeur normal identifie (a l'adresse de) un seul objet en mémoire. Un pointeur vers un membre d'une classe identifie ce membre dans toute instance de la classe. L'exemple suivant déclare une classe, Window
, et certains pointeurs vers des données membres.
// 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()
{
}
Dans l’exemple précédent, pwCaption
est un pointeur vers n’importe quel membre de classe Window
de type char*
. Le type de pwCaption
est char * Window::*
. Le fragment de code suivant déclare des pointeurs vers les fonctions membres SetCaption
et GetCaption
.
const char * (Window::* pfnwGC)() = &Window::GetCaption;
bool (Window::* pfnwSC)( const char * ) = &Window::SetCaption;
Les pointeurs pfnwGC
et pfnwSC
pointent respectivement vers GetCaption
et SetCaption
de la classe Window
. Le code copie directement des informations vers le titre de la fenêtre à l'aide du pointeur vers le membre pwCaption
:
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';
La différence entre les opérateurs et les .*
->*
opérateurs (opérateurs pointeur à membre) est que l’opérateur .*
sélectionne les membres en fonction d’un objet ou d’une référence d’objet, tandis que l’opérateur ->*
sélectionne des membres via un pointeur. Pour plus d’informations sur ces opérateurs, consultez Expressions avec des opérateurs pointeur vers membre.
Le résultat des opérateurs pointeur à membre est le type du membre. Dans ce cas, il s’agit de char *
.
Le fragment de code suivant appelle les fonctions membres GetCaption
et SetCaption
à l'aide de pointeurs vers des membres :
// 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 );
Restrictions sur les pointeurs vers des membres
L’adresse d’un membre statique n’est pas un pointeur vers un membre. Il s’agit d’un pointeur normal vers l’instance du membre statique. Une seule instance d’un membre statique existe pour tous les objets d’une classe donnée. Cela signifie que vous pouvez utiliser les opérateurs d’adresse ordinaire (&) et de déréférencement (*).
Pointeurs vers des membres et des fonctions virtuelles
L’appel d’une fonction virtuelle par le biais d’une fonction pointeur à membre fonctionne comme si la fonction avait été appelée directement. La fonction correcte est recherchée dans la table v et appelée.
La clé du bon fonctionnement des fonctions virtuelles est, comme toujours, de les appeler via un pointeur vers une classe de base. (Pour plus d’informations sur les fonctions virtuelles, consultez Fonctions virtuelles.)
Le code suivant montre comment appeler une fonction virtuelle via un pointeur de fonction membre :
// 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
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour