6 votes

Surcharge des fonctions constantes

Je ne comprends pas pourquoi le code suivant ne produit pas d'erreur, car les arguments passés à l'affichage sont du même type, à savoir char const fait vraiment une différence ?

#include<iostream>

using namespace std;

void display(char *p)
{
    cout<<p;
}
void display(const char *p)
{
    cout<<p;
}

int main()
{
    display("Hello");
    display("World");
}

EDIT D'après les réponses, le premier affichage n'est jamais appelé, ce qui est correct, tout comme la sortie.

Mais si je faisais comme ça :

int main()
{
    char *p="Hello";
    display(p);//now first display is called.
    display("World");
}

Le compilateur donne un warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] Cela signifie-t-il que la chaîne n'est plus considérée comme une constante ?

11voto

Xaqq Points 2023

const char* y char * ne sont en fait pas les mêmes. Les seconds permettent de modifier le point char tandis que le premier l'empêchera.

Notez également que si c'était des méthodes de classe , void display() y void display() const seraient également des surcharges valables. La dernière impliquerait que la méthode ne doit pas changer l'état de l'objet.

Considérez ce code :

void    display(char *s)
{
  std::cout << "Display" << std::endl;
}

void    display(const char *s)
{
  std::cout << "Display with const" << std::endl;
}

int     main()
{
  char  *str = strdup("boap");
  const char *str2 = "toto";
  /* It is a string literral "bound" as a char *.                                                                               
     Compiler will issue warning, but it still compiles.                                                                        
     Avoid to do that, it's just an exemple */
  char  *not_safe = "not_safe";

  display("llama");
  display(str2);
  display(str);
  display(not_safe);
}

Ceci imprimera Display with const deux fois, et puis deux fois Display . Voir . Voyons maintenant pourquoi :

  • "llama" est un littéral de chaîne de caractères, puis est résolu comme un const char * .
  • str2 est un pointeur vers un littéral de chaîne de caractères. Puisque son type est const char* cela tourne aussi autour de la const surcharge.
  • not_safe est également un pointeur vers un littéral de chaîne de caractères. Cependant, son type est char * : ce n'est pas correct . La mémoire vers laquelle elle pointe est en lecture seule, et essayer de la modifier entraînera un crash. Cependant, le type de la variable est toujours char * donc cette résolution à la non- const surcharge.
  • str est un char * et la chaîne vers laquelle il pointe n'est pas en lecture seule. La modification de son contenu est valide, et puisque son type est char * il sera résolu par la surcharge non-const.

3voto

juanchopanza Points 115680

Le problème est que les chaînes littérales telles que "Hello" y "World" avoir le type const char[6] . Cela peut se dégrader en const char* mais pas à char* . Donc la surcharge prenant const char* ,

 void display(const char *p);

est le meilleur choix. Comme le souligne @JamesKanze, il serait possible pour une fonction prenant char* pour accepter une chaîne littérale, mais tenter de modifier les données pointées vers elle entraînerait un comportement non défini. Pour cette raison, il n'est pas sûr de passer des chaînes de caractères à de telles fonctions. Avec des paramètres d'avertissement appropriés, GCC produit ce qui suit :

avertissement : conversion dépréciée d'une constante de chaîne en 'char*'.

En tout cas, en présence de deux surcharges comme celles que vous avez montrées, celle qui prend const char* gagne.

0voto

Agentlien Points 3163

Les arguments passés aux deux fonctions ne sont en fait pas les mêmes.

Le premier prend un char* : Un pointeur vers un char .

Le second prend un const char* : Un pointeur vers un const char .

Vous voyez donc que la différence ici réside en fait dans le fait que le pointeur pointe vers un objet qui peut être modifié ou non. C'est définitivement une propriété sur laquelle vous voulez être capable de surcharger une fonction.

0voto

nijansen Points 3998

Le fait de pouvoir modifier un objet ou non est définitivement une information utile en fonction de laquelle vous pouvez vouloir invoquer un comportement différent ! Considérez ceci :

void foo(int * p) { ++(*p); }
void foo(int const * p) { std::cout << *p << '\n'; }

0voto

maditya Points 3372

Les tailles des chaînes "Hello" et "World" sont connues au moment de la compilation et ne peuvent pas être modifiées. Ce sont des tableaux de caractères constants au moment de la compilation.

En C et C++, un tableau, par ex. char a[6] peuvent être référencés à l'aide d'un pointeur, à savoir a est en fait un char * . Puisque les tableaux pour "Hello" et "World" ne doivent pas être modifiés à l'exécution, leur type est essentiellement const char * .

Le compilateur reconnaît cela et effectue la résolution de surcharge pour display correctement, car une seule des fonctions ( display(const char* p) ) prend un const char* comme argument. C'est pourquoi il n'y a aucune ambiguïté dans les deux fonctions, et vous n'obtenez pas l'erreur à laquelle vous vous attendiez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X