Je suis tombé sur une fonction d'instance de classe qui avait besoin de changer temporairement une variable d'instance de classe, puis de la restaurer lorsque la fonction était terminée. La fonction avait des instructions de retour partout, et avant chaque retour il y avait une déclaration de restauration. Cela m'a semblé désordonné, sans parler de l'effrayant quand une exception est levée.Manière générale de réinitialiser une variable membre à sa valeur d'origine en utilisant la pile?
Comme une amélioration je suis venu avec cette généralisation en utilisant une définition de classe interne. Voici un exemple de programme pilote (restaurateur de classe).
class Unwind {
private:
bool b_active_; ///< the thing I want to be restored
template<typename T>
class restorer {
T* ref_;
T save_;
public:
restorer(T* perm) : ref_(perm), save_(*ref_) {};
~restorer() { *ref_ = save_; }
};
public:
Unwind() : b_active_(false) {};
void a() { out("a in"); b(); out("a end"); }
void b() {
out("b in");
{
restorer<bool> trust_in_the_stack(&b_active_); // "restorer" created on the stack
b_active_ = true; // change b_active_ only while "within" b()
c();
out("b inner end");
}
out("b end");
}
void c() { out("c in"); d(); out("c end"); }
void d() { out("d in"); cout << "deepest" << endl; out("d end"); }
void out(const std::string& msg) {
std::cout << msg << ": " << b_active_ << std::endl;
}
};
int main() { Unwind u; u.a(); return 0; }
La sortie en utilisant g ++ 4.2.3 (-Wall) était:
a in: 0 b in: 0 c in: 1 d in: 1 deepest d end: 1 c end: 1 b inner end: 1 b end: 0 a end: 0
Ce qui est ce que je pense à "fin b". Je pensais que définir le restaurateur de classe à l'intérieur de la classe Unwind aide à décourager les abus.
Ma question est la suivante: existe-t-il une façon générale et plus sûre de le faire? Je suis inquiet pour les problèmes de la vie. Editer: Veuillez supposer qu'il n'y a pas de threads, mais des méthodes "en aval" sur la pile qui modifient le comportement basé sur cet indicateur b_active_.
Je pense qu'il vaudrait mieux remplacer save _ (* ref_) dans la liste d'initialisation avec save _ (* perm). save _ (* ref_) peut vous mordre un jour, quand quelqu'un change l'ordre des déclarations dans votre classe. –
@Maciej H: Bon point, merci! – piyo