Modifier un attribut dans une méthode constante

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,
je voudrais savoir s'il y avait un moyen de rendre un attribut spécifique modifiable par une fonction constante de l'objet ? En gros, j'ai ça :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class maClasse
{
    private:
        int maVariable;

    public:
        void maFonction() const
        {
            //Des calculs
            maVariable = 42; // Modification de maVariable (et uniquement celle-ci) possible
        }

};

À noter que je ne peux pas rendre ma fonction non constante, ça serait trop simple.

Merci d'avance ! :-)

La curiosité est le plus beau des défauts

+0 -0
Auteur du sujet

Et bien je modifie une classe qui n'est pas de moi, qui est un module d'un programme plus gros. Et donc mes actions sont assez limitées. La fonction principale qui est appelée est constante lors de l'utilisation de ma classe, et donc, toutes les fonctions que j'ajoute doivent l'être aussi. Ce qui limite grandement ma marge de manœuvre, même pour un attribut que j'ai créé.

Si je voulais éviter ça, je devrais créer la variable dans la première fonction et la transférer dans toutes les fonctions qui en ont besoin, ce qui est un peu lourd.

Merci, pour mutable, je vais regarder ça :-)

La curiosité est le plus beau des défauts

+0 -0

C'est donc un cas de contournement du code et pas une utilisation "légitime" de mutable. Honnêtement, c'est le genre de chose qui peut sembler être une bonne une chose a court terme, mais qui est généralement casse-gueule sur le long terme. Bref, je déconseille (a tes risques et périls)

+0 -0
Auteur du sujet

Quelle serait une utilisation légitime de mutable ?

Je ne vois pas trop ça comme un contournement, puisque j'ajoute un attribut à la classe, il n'y a uniquement mon attribut qui peut être modifié. Les attributs d'origine, eux, restent intacts.

Édité par Dark Patate

La curiosité est le plus beau des défauts

+0 -0

Une utilisation classique, c'est un cache. Par exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Test {
public:
    int doSomething() const {
        const int result = doSomethingComplex();
        return result;
    }
};

class TestWithMutable {
public:
    int doSomething() const {
        if (resultNeedToBeUpdated()) {
            m_result = doSomethingComplex();
        }
        return m_result;
    }
private:
    mutable int m_result{};
};

Le problème "sur le long terme" est conceptuel : à partir du moment où tu "brises" l'interface publique de ta classe (ie dire aux utilisateurs de ta classe que cette fonction est const alors que ce n'est pas le cas), tu augmentes le risque de mauvaise utilisation, en particulier lorsque le code sera mis à jour dans 6 mois et que la personne ne voit pas le mutable.

A toi de voir si le contexte correspond à une utilisation de mutable et évaluer le risque à long terme

Édité par gbdivers

+0 -0
Auteur du sujet

Ok, et bien en réfléchissant bien, même en passant la variables de fonctions en fonctions je ne pourrais faire ce que je voudrais.
J'avais essayé de faire avec une variable globale pour résoudre le problème (oui, je sais, c'est pas forcément mieux que mutable :p ) mais le compilateur m'avait sortie pleins d'erreur :-).

Dans ton exemple, l'utilisation de mutable permet de stocker la valeur de retour qq part, c'est ça ?

Pour mon code, en gros, j'ai besoin d'ajouter une ligne dans un tableau (l'attribut mutable) à chaque fois que la fonction est appelée, pour stocker un id d'appel (une variable statique). Ce tableau n'a d'intérêt que dans ces fonctions.

Après, je vais voir si je trouve pas un autre moyen.
Merci en tout cas !

Édité par Dark Patate

La curiosité est le plus beau des défauts

+0 -0

mutable permet simplement de modifier une variable membre dans une fonction membre const.

Tu veux faire une espece de log d'appel des fonctions ? Mutable fonctionnera ici (et est probablement une utilisation "légale" dans ce cas)

Édité par gbdivers

+0 -0
Auteur du sujet

Pas tout à fait, en fait c'est pour rendre mon code plus propre (si, si :p ). En gros, pour simplifier, la classe (deux pour être exact) que j'utilise créé un bloc de calcul pour le logiciel, à la manière d'un bloc sous Simulink ou Labview. Je peux ajouter des entrées et sorties à ce bloc avec de simples fonctions, genre addInput(...). Le problème c'est que l'ordre d'appel de cette fonction me donne l'id de l'entrée, ainsi le dixième appel de la fonction me donnera l'id 9.

Et donc, j'utilise mon tableau pour garder une liste de toutes mes entrées/sorties. Alors que dans le code d'exemple, ils se contentaient d'écrire en dur l'id de chaque entrée/sortie. Ce qui n'est pas modulaire, car il suffit d'intervertir deux création d'entrée/sortie pour devoir changer tout les id. De plus, c'est moins lisible, c'est pour ça que mon tableau est un std::map<std::string, int>.

Ça ressemble un peu à un log d'appel, puisque que je met à jour mon tableau à chaque fois que j'appel la fonction pour garder l'id d'une entrée/sortie en mémoire.

Édité par Dark Patate

La curiosité est le plus beau des défauts

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte