Question

Je ne comprends pas très bien pourquoi on m'a demandé de renvoyer const foo d'un opérateur binaire en c ++ au lieu de foo.

J'ai lu "Thinking in C ++" de Bruce Eckel, et dans le chapitre sur la surcharge d'opérateurs, il dit que "en faisant la valeur de retour [d'un opérateur binaire surchargé] const, vous déclarez que seule une fonction membre const peut être appelée pour cette valeur de retour. Ceci est correct, car cela vous empêche de stocker des informations potentiellement précieuses dans un objet qui sera probablement perdu ".

Cependant, si j'ai un opérateur plus qui renvoie const et un opérateur d'incrément de préfixe, ce code n'est pas valide:

class Integer{
int i;

public:
    Integer(int ii): i(ii){ }
    Integer(Integer&);

    const Integer operator+();
    Integer operator++();
};


int main(){

Integer a(0);
Integer b(1);

Integer c( ++(a + b));
}

Pour autoriser ce type d’assignation, ne serait-il pas judicieux que l’opérateur + renvoie une valeur non-const? Cela pourrait être fait en ajoutant const_casts, mais cela devient assez volumineux, n'est-ce pas?

Merci!

Était-ce utile?

La solution

Quand vous dites ++ x, vous dites "ajoutez 1 à x, stockez le résultat dans x et dites-moi ce que c'était". C'est l'opérateur de préincrémentation. Mais, en ++ (a + b), comment êtes-vous censé "stocker le résultat dans un + b"?

Vous pouvez certainement stocker le résultat dans le temporaire, qui contient actuellement le résultat de a + b, qui disparaîtrait assez tôt. Mais si vous ne vous souciez pas vraiment de savoir où le résultat a été stocké, pourquoi l’avez-vous incrémenté au lieu d’en ajouter un?

Autres conseils

Pour info, ++ (a + b) est illégal, même avec les POD (anciens types de données simples, comme int ). Il est donc logique de ne pas l'autoriser pour vos propres types de classe. Essayez ceci:

int a = 1;
int b = 2;
int c = ++(a+b);

GCC renvoie l'erreur : lvalue requise en tant qu'opérande d'incrémentation .

Dans votre cas, il serait préférable que votre constructeur de copie prenne un argument const Integer et crée votre Integer c comme ceci:

Integer c(a + b + Integer(1));

Les constructeurs de copie utilisent généralement une référence const pour résoudre ce problème.

(Avoir une copie non-const implique un certain transfert de ressources, ce qui peut être utile parfois, mais dans 99% des cas, ce n'est pas nécessaire)

Je pense que l'exemple de OP conviendrait à la question si l'opérateur d'addition est remplacé par un autre opérateur binaire renvoyant une référence, par exemple un opérateur d'affectation:

Integer c( ++(a = b));

Je suis venu ici pour me demander si je devais demander à mon opérateur d'affectation de renvoyer une référence const ou non-const. Quelques tutoriels utilisez des versions non constantes, contrairement au conseil de "Thinking in C ++". Et d'autres références expliquent ce raisonnement:

  

Notez que la référence renvoyée n'est pas déclarée const. Cela peut être un peu déroutant, car cela vous permet d’écrire des choses folles comme celle-ci:

     
    

MyClass a, b, c;

         

...

         

(a = b) = c; // Quoi ??

  
     

À première vue, vous voudrez peut-être éviter de telles situations en demandant à operator = de renvoyer une référence const. Cependant, des instructions comme celle-ci fonctionneront avec des types primitifs. Et, pire encore, certains outils reposent en réalité sur ce comportement. Par conséquent, il est important de renvoyer une référence non-const de votre opérateur =. La règle de base est la suivante: "Si cela convient assez bien pour ints, il l'est assez bien pour les types de données définis par l'utilisateur".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top