2010-07-09 5 views
1

Dans le livre intitulé « Utilisation de C++ » par Rob McGregor, il est suivant l'exemple de l'utilisation de l'opérateur pointeur à membreDérivation un type de pointeur sur l'élément de classe non-pointeur

class mycls 
{ 
public: 
    int member; 
    int *ptr; 
}; 

void main() 
{ 
    mycls MyClass; 

    // Derive a pointer type to the non-pointer class member 
    int mycls::*member = &mycls::member; 

    MyClass.ptr = new int; 
    mycls* pMyClass = &MyClass; 

    pMyClass->*member = 5; 
    *MyClass.ptr = 10; 

    cout << "pMyClass->*member = " << pMyClass->*member << "\n"; // pMyClass->*member = 5 
    cout << "MyClass.*member = " << MyClass.*member << "\n"; // MyClass.*member = 5 
    cout << "*MyClass.ptr = " << *MyClass.ptr << "\n"; // *MyClass.ptr = 10 
    cout << "*pMyClass->ptr = " << *pMyClass->ptr << "\n"; // *pMyClass->ptr = 10 

    delete MyClass.ptr; 
} 

Dans cet exemple, je ne suis pas comprendre pourquoi variable membre mycls::member devient peut-être un pointeur après (deviner) cette ligne de code:

int mycls::*member = &mycls::member; 

Qu'est-ce que cela fait?

Répondre

5

Supposons que vous ayez une variable locale:

int member; 

Vous pouvez faire un pointeur avec:

int *ptr = &member; 

Pour obtenir le pointeur sur la syntaxe de membre, nous ajoutons simplement mycls:: dans les endroits appropriés :

int mycls::*member = &mycls::member; 

Il pourrait être plus clair avec un exemple qui montre comment le pointeur peut basculer entre les membres de la classe qui sont du type correct:

class C 
{ 
public: 
    int a; 
    int b; 
}; 

void main() 
{ 
    // make pointer to member, initially pointing to a 
    int C::*ptrToMember = &C::a; 

    C x; 
    C *ptrToObj = &x; // make pointer to object x 

    ptrToObj->*ptrToMember = 2; // store in a; 

    ptrToMember = &C::b; // change pointer to b 

    ptrToObj->*ptrToMember = 3; // store in b; 
} 

Notez la façon dont nous créons le pointeur sur l'élément a avant que nous avons créé un objet de type C. C'est seulement un pointeur vers un membre, pas un pointeur vers le membre d'un objet spécifique. Dans les étapes du «magasin», nous devons dire quel objet ainsi que quel membre.

Mise à jour

Dans les commentaires de l'OP a demandé si c'est le même:

int *ptr = &(ptrToObj->a); 

Non, ce n'est pas. C'est un pointeur vers n'importe quel int, n'importe où dans la mémoire.

La façon la plus simple de comprendre cela est de penser à ce que cela signifie techniquement. Un "pointeur" est un absolu emplacement dans la mémoire: où trouver un objet. Un "pointeur vers membre" est un emplacement relatif, parfois appelé un décalage: où trouver un objet dans le stockage d'un objet externe. En interne, ils ne sont que des chiffres. Un pointeur vers membre doit être ajouté à un pointeur ordinaire pour créer un autre pointeur.

Donc, si vous avez un pointeur vers un objet (un int est un objet!), Vous pouvez l'utiliser pour changer ce qui est stocké à cet endroit absolu en mémoire:

*ptr = 123; 

Mais si vous avez un pointeur à membre, ce n'est pas un emplacement de mémoire. C'est un décalage, un montant à ajouter à un emplacement de mémoire. Vous ne pouvez pas l'utiliser seul. Vous devez « ajouter » à un pointeur d'objet:

ptrToObj->*ptrToMember = 132; 

Cela signifie: aller à l'emplacement en mémoire ptrToObj, déplacer ensuite le long de la distance ptrToMember.

+0

Est-ce aussi valable et signifie la même chose, puis « int * ptr = & (ptrToObj-> a); " –

+0

C'est valide, mais ce n'est pas la même chose. Voir ma mise à jour –

0

Le caractère astérisque dans la déclaration fait partie du type.

Votre déclaration se décompose en

Type: int mycls::*

Nom de la variable: member

Initialiser: = &mycls::member

Cette nouvelle member variables points est un pointeur de membre à un int détenu dans un mycls. Il ne doit pas pointer vers un mycls::member.

2

Il a appelé le membre de classe member et le pointeur vers le membre member, ce qui a perturbé le problème. Est-ce que les renommer comme ça aide?

Classe:

class SampleClass 
{ 
public: 
    int m_data; 
    int* m_pointer; 
}; 

Utilisation:

int main() 
{ 
    SampleClass sample; 

    // Derive a pointer type to the non-pointer class member 
    int SampleClass::*pointerToMember = &SampleClass::m_data; 

    sample.m_pointer = new int; 
    SampleClass* pSample = &sample; 

    pSample->*pointerToMember = 5; 
    *sample.m_pointer = 10; 

    // pSample->*pointerToMember = 5 
    cout << "pSample->*pointerToMember = " 
     << pSample->*pointerToMember << "\n"; 

    // sample.*pointerToMember = 5 
    cout << "sample.*pointerToMember = " 
     << sample.*pointerToMember << "\n"; 

    // *sample.m_pointer = 10 
    cout << "*sample.m_pointer = " 
     << *sample.m_pointer << "\n"; 

    // *pSample->m_pointer = 10 
    cout << "*pSample->m_pointer = " 
     << *pSample->m_pointer << "\n"; 

    delete sample.m_pointer; 
} 

[Code]

Edit: Re « Je suis toujours currious si int *ptr = &(ptrToObj->a); est le même que l'utilisation de pointeur vers un membre comme dans le livre ":

Ce n'est pas un pointeur-à-membre . C'est juste un pointeur normal vers la mémoire qui se trouve dans un objet.

Vous pouvez voir la syntaxe utilisée ici:

Classe:

class C 
{ 
public: 
    int a; 
    int b; 
}; 

Utilisation:

int main() 
{ 
    // make pointer to member, initially pointing to a 
    int C::*ptrToMember = &C::a; 

    C x = {10, 11}; 
    C *ptrToObj = &x; // make pointer to object x 

    cout << "a initial value: " << ptrToObj->*ptrToMember << endl; 

    ptrToObj->*ptrToMember = 2; // store in a; 

    cout << "a after change: " << ptrToObj->*ptrToMember << endl; 

    ptrToMember = &C::b; // change pointer to b 

    cout << "b initial value: " << ptrToObj->*ptrToMember << endl; 

    ptrToObj->*ptrToMember = 3; // store in b; 

    cout << "b after change: " << ptrToObj->*ptrToMember << endl; 


    int* ptr = &(ptrToObj->a); 
    cout << "ptr to a: " << *ptr << endl; 

    ptr = &(ptrToObj->b); 
    cout << "ptr to b: " << *ptr << endl; 
} 

[Code]

+0

Il est utile d'avoir une meilleure compréhension de ce que le code fait de cette façon, mais ce que je n'ai pas vraiment compris (maintenant je le fais grâce à Daniel) est un concept de pointeur vers un membre de la classe. Je suis toujours curieux si "int * ptr = & (ptrToObj-> a);" est le même que d'utiliser un pointeur sur un membre comme dans le livre. –

+0

@Sergej: Voir ma modification. – Bill

Questions connexes