6
votes

Pourquoi puis-je appeler un pointeur de fonction membre non-Const d'une méthode const?

Un collègue a posé des questions sur un code comme celui-ci qui avait à l'origine des modèles à l'origine.

J'ai supprimé les modèles, mais la question principale reste: pourquoi cela compilait-il OK? P>

#include <iostream>

class X
{
public:
     void foo() { std::cout << "Here\n"; }
};

typedef void (X::*XFUNC)() ;

class CX
{
public:
    explicit CX(X& t, XFUNC xF) : object(t), F(xF) {}      
    void execute() const { (object.*F)(); }
private:
    X& object;
    XFUNC F;
}; 

int main(int argc, char* argv[])
{   
    X x; 
    const CX cx(x,&X::foo);
    cx.execute();
    return 0;
}

c++

0 commentaires

5 Réponses :


8
votes

Dans ce contexte objet est une référence à un x , pas un référence à un const x . Le qualificatif const serait appliqué sur le membre (c'est-à-dire la référence, mais les références ne peuvent pas être const ), non à l'objet référencé.

Si vous changez votre Définition de la classe à ne pas utiliser de référence: xxx

Vous obtenez l'erreur que vous attendez.


2 commentaires

Néanmoins, avec const -methods, il ne faut-il que appeler const -methods sur les objets membres, n'est-ce pas?


Le membre est la référence, pas l'objet référencé.



11
votes

Le const code> NESS de exécuter () code> n'affecte que le pointeur code> de la classe. Il rend le type de ceci code> A const t * code> au lieu de t * code>. Ce n'est pas un "profond", cependant - cela signifie seulement que les membres eux-mêmes ne peuvent pas être changés, mais tout ce qu'ils indiquent ou font encore référence. Votre membre objet code> ne peut déjà pas être modifié, car les références ne peuvent pas être re-assises pour signaler quoi que ce soit d'autre. De même, vous n'êtes pas changer em> le membre F code>, il suffit de la désirer en tant que pointeur de fonction membre. Donc, tout cela est autorisé, et d'accord pouvez. Vous pouvez toujours appeler des fonctions de membre const sur les objets constants, donc pas de changement là-bas. P>

Pour illustrer: P>

class MyClass
{
public:
    /* ... */

    int* p;

    void f() const
    {
        // member p becomes: int* const p
        *p = 5;   // not changing p itself, only the thing it points to - allowed
        p = NULL; // changing content of p in const function - not allowed
    }
};


1 commentaires

Il est important de noter que vous pouvez essentiellement traiter un t & comme t * cons . Quoi qu'il en soit, je conviens que la propagation peu profonde de const est étrange, mais nous avons ensuite une copie peu profonde par défaut ...



4
votes

L'instance objet de classe x n'est pas Const. Il est simplement référencé par un objet qui est constitué. La const-ness s'applique récursivement aux sous-observations, pas à des objets référencés.

par la logique alternative, une méthode const ne serait pas en mesure de modifier rien . Qui s'appelle une "fonction pure", un concept qui n'existe pas dans la norme actuelle C ++.


0 commentaires

2
votes

Vous appelez foo sur objet , pas sur ceci .

Etant donné que objet est déclaré sous la forme d'un x & , dans une constante CX, il est en fait un x & const (qui n'est pas le même que const x & ) vous permettant d'appeler des méthodes non constituées dessus.


1 commentaires

J'ai l'impression que vous auriez dû mentionner "& const" est absurde dans le langage, car il n'existe pas de "redevance de référence".



0
votes

Une manière utile de penser à ce sujet pourrait être que votre objet X n'est pas membre de CX du tout.


1 commentaires

Vous pourriez y penser comme ça, mais peu importe si c'est ou non. Cette classe pourrait avoir une instance x ( objet ) en tant que membre et également un élément de référence pour faire référence à cela. Alors vous constaterez que vous ne pouvez pas faire (objet. * F) (); , mais peut toujours faire (référence. * F) (); même si Il fait référence exactement à la même chose que est membre de CX.