3
votes

Comment la fonction membre comprend-elle que l'objet est obtenu en déréférençant un pointeur const?

J'ai créé un pointeur const qui pointe vers une instance d'abject allouée dynamiquement.Je ne pouvais pas comprendre que l'objet lui-même est const ou non.

J'ai d'abord essayé d'appeler une fonction membre non-const en utilisant le pointeur, comme prévu cela a provoqué une erreur de compilation car (c'est mon explication, je ne sais pas si c'est vrai ou non) ce pointeur créé par la fonction membre est assigné à ce pointeur const. Cela n'a rien donné.

Deuxièmement, j'ai essayé de déréférencer le pointeur et d'appeler cette fonction membre non-const. Je pensais que ce pointeur créé par la fonction membre ne sera plus un pointeur const car la compilation ne peut pas connaître l'objet retourné par p (à savoir * p ) est retourné par un pointeur const ou non. Il s'avère que je me suis trompé.

Comment la fonction membre comprend-elle cela?

Je pensais que la ligne étiquetée 2 ne créera pas de compilation Erreur. Cela provoque une erreur de compilation. Le message d'erreur est:

"a.cpp: In function ‘int main()’:
a.cpp:21:13: error: passing ‘const A’ as ‘this’ argument discards qualifiers [-fpermissive]
    p->print(); //1 causes compile error
             ^
a.cpp:10:9: note:   in call to ‘void A::print()’
  void   print()
         ^~~~~
a.cpp:22:15: error: passing ‘const A’ as ‘this’ argument discards qualifiers [-fpermissive]
    (*p).print(); //2 causes compile error
               ^
a.cpp:10:9: note:   in call to ‘void A::print()’
  void   print()
         ^~~~~
#include<iostream>

class A
{
    int a=4;
public:
    A()
    {}

 void   print()
    {
        std::cout<<a<<std::endl;
    }
};


int main()
{
    const A* p = new A();  

   p->print(); //1 causes compile error
   (*p).print(); //2 causes compile error


  return 0;
}


10 commentaires

Je ne comprends pas de quoi vous êtes confus. Si on déréférence const A * , il en reste const A , non?


p est un pointeur vers l'objet const , tandis que print n'est pas marqué comme fonction const. Qu'est-ce qui est surprenant?


@SergeyA C'est surprenant si vous pensez que l'exactitude de const est appliquée sur la base d'une expression primaire plutôt que par le biais du système de types.


alors const A * p = nouveau A (); et const A * p = new const A (); n'a pas de différence non?


Ils sont légèrement différents, mais pas d’une manière particulièrement utile, et je n’ai jamais vu new const A en code réel. Voir stackoverflow.com/questions/1927477/… .


pourquoi l'objet créé est-il converti en type const? Je veux dire que je crée un entier non const et un entier const qui pointe vers cet entier.


Parce que vous l'avez fait lorsque vous l'avez affecté à une variable de type const A * . C ++ vous permet de convertir implicitement un objet non const en type const, car c'est une chose totalement sûre à faire.


@Sneftel merci, maintenant je comprends :)


veuillez inclure les messages d'erreur textuellement au lieu de les paraphraser. L'appeler "classique" est un peu déplacé à mon humble avis, qu'est-ce qui est classique à ce sujet?


@ formerlyknownas_463035818 okey


3 Réponses :


6
votes

Les variables ont des types et peuvent donc être const ou non const, mais les expressions ont aussi des types. Le type de (* p) est const A , et vous ne pouvez pas appeler une méthode non-const d'un type const.


1 commentaires

Hmm vous dites que l'objet créé par new est const? Pourquoi parce que je peux pointer un pointeur entier const vers un entier non const. Y a-t-il une raison ? ---- J'ai eu ma réponse ----



3
votes

Il n'y a aucune différence entre (1) et (2). (1) est le sucre de syntaxe pour (2). Vous devez définir la méthode d'impression en tant que const afin de l'appeler pour l'objet const.

void print() const { ... }


0 commentaires

3
votes

Comme il a déjà été noté, les expressions ont des types et le type de (* p) est const A. Vous ne pouvez pas appeler une fonction non-const sur un objet de type const mais vous pouvez appeler une fonction membre const. Les fonctions membres peuvent avoir un qualificatif const qui les marquera comme pouvant être invoquées sur des objets const ou des pointeurs vers des objets const.

void print() const
{
   std::cout<<a<<std::endl;
}

Cela rendra votre code compilé. et il semble que c'est ce que vous aviez l'intention de faire de toute façon.


0 commentaires