web-dev-qa-db-fra.com

newbie question: c ++ conversion en conversion non-const

Le mot clé const m'ennuie énormément ces derniers temps, car je ne le connais pas bien. J'avais un vecteur qui stockait tous les pointeurs const tels que vector<const BoxT<T> *> *Q_exclude et, dans le constructeur d'une autre classe, il me fallait un élément de cette file d'attente qui soit passé en paramètre et affecté à un membre non const. Ma question est: 

Comment attribuer une variable const à une variable non-const? Je sais que cela n’a aucun sens car, après tout, un const est un const et ne devrait en aucun cas être modifié. Mais cette variable de membre ennuyante doit VRAIMENT être changée au cours du processus! Je pourrais aussi changer le type de données dans le vecteur pour qu'il ne soit pas constant, mais ce serait trop de travail. Ou est-ce que quelqu'un sait comment éviter une telle situation? 

33
Shang Wang

Vous pouvez assigner un objet const à un objet non -const parfaitement. Comme vous copiez et créez ainsi un nouvel objet, constness n'est pas violé.

Ainsi:

int main() {
   const int a = 3;
   int b = a;
}

C'est différent si vous voulez obtenir un pointeur ou une référence à l'objet original const:

int main() {
   const int a = 3;
   int& b = a;       // or int* b = &a;
}

//  error: invalid initialization of reference of type 'int&' from
//         expression of type 'const int'

Vous pouvez utiliser const_cast pour modifier le type de sécurité si vous le devez vraiment, mais rappelez-vous que vous faites exactement cela: vous débarrasser du type de sécurité. Il est still indéfini de modifier a à b dans l'exemple ci-dessous :

int main() {
   const int a = 3;
   int& b = const_cast<int&>(a);

   b = 3;
}

Bien que la compilation se fasse sans erreur, tout peut arriver, y compris ouvrir un trou noir ou transférer toutes vos économies durement gagnées sur mon compte bancaire.

Si vous en êtes arrivé à ce que vous pensez être une obligation de le faire, je revisiterais votre conception de toute urgence car il y a quelque chose qui ne va pas avec.

67

Changer un type de constante mènera à un Comportement non défini

Cependant, si vous avez un objet d'origine non-const pointé par un pointeur sur const ou référencé par une référence-à-const, vous pouvez utiliser const_cast pour supprimer cette constante.

Jeter la constance est considéré comme un mal et devrait  ne pas être évité. Vous devriez envisager de changer le type des pointeurs que vous utilisez dans vector en non-const si vous souhaitez modifier les données par le biais de celui-ci.

7
Alok Save

Le code réel pour rejeter la constance de votre pointeur serait:

BoxT<T> * nonConstObj = const_cast<BoxT<T> *>(constObj);

Mais notez que c'est vraiment de la triche. Une meilleure solution serait soit de comprendre pourquoi vous souhaitez modifier un objet const et de redéfinir votre code afin de vous éviter de .... veux vraiment que ces articles soient en lecture seule après tout.

3
Jeremy Friesner
void SomeClass::changeASettingAndCallAFunction() const {
    someSetting = 0; //Can't do this
    someFunctionThatUsesTheSetting();
}

Une autre solution consiste à appeler ladite fonction entre les modifications apportées aux variables utilisées par la fonction const. Cette idée a été ce qui a résolu mon problème étant donné que je n'étais pas enclin à changer la signature de la fonction et que je devais utiliser la méthode "changeASettingAndCallAFunction" en tant que médiateur:

Lorsque vous appelez la fonction, vous pouvez d’abord modifier le paramètre avant l’appel, ou (si vous n’êtes pas enclin à jouer avec le lieu invoquant), appelez peut-être la fonction pour laquelle le changement de variable doit être propagé mon cas).

void SomeClass::someFunctionThatUsesTheSetting() const {
     //We really don't want to touch this functions implementation
     ClassUsesSetting* classUsesSetting = ClassUsesSetting::PropagateAcrossClass(someSetting);
     /*
         Do important stuff
     */
}

void SomeClass::changeASettingAndCallAFunction() const {
     someFunctionThatUsesTheSetting();
     /*
         Have to do this
     */
}

void SomeClass::nonConstInvoker(){
    someSetting = 0;
    changeASettingAndCallAFunction();
}

Maintenant, quand une référence à "someFunctionThatUsesTheSetting" est invoquée, elle sera invoquée avec la modification de someSetting.

0
djg