Tourné les droits d’utilisateur à on et à off Retournons sur le problème de droit d’utilisateur. Les conteneurs qui prenaient les objets par valeur se fiche normalement des droits d’utilisateurs parce qu’ils possèdent clairement l’objet qu’ils contiennent. Mais si votre conteneur prend des pointeurs (ce qui est plus commun avec le C++, spécialement avec le polymorphisme), puis c’est vraiment habituel que ces pointeurs peuvent aussi être utilisé autre pars dans le programme, et vous n’avez pas nécessairement besoin de supprimer l’objet parce que l’autre pointeur dans le programme peut être référencer à un objet détruit. Pour prévenir ceci d’arriver, vous devez considérez les droits d’utilisateur quand vous concevez et utilisez un conteneur. Beaucoup de programme sont plus simple que cela, et ne rencontre pas le problème de droits d’utilisateur : Un conteneur prend des pointeurs sur des objets qui sont utilisés seulement par ce conteneur. Dans ce cas les droit d’utilisateur sont vraiment franc: Le conteneur possèdent cet objet. La meilleure approche pour manipuler le problème de droits d’utilisateur est de donner un choix au programme client. C’est souvent accompli par un argument du constructeur qui par défaut indique le droit d’utilisateur (le simple cas). En addition il peut avoir des fonctions “get” et “set” pour voir et modifier le droit d’utilisateur du conteneur. Si le conteneur a des fonctions pour supprimer un objet, l’état du droit d’utilisateur usuellement affecte cette suppression, donc vous devrez aussi trouver des options pour contrôler la destruction dans la fonction de suppression. Vous pouvez peut-être ajouter une donnée de droit d’utilisateur pour chaque élément dans le conteneur, donc chaque position devrait savoir si il devrait être détruit ; c’est une variante du compteur de référence, excepté que le conteneur et pas l’objet connaît le nombre de références pointant sur un objet. //: C16:OwnerStack.h // Stack with runtime conrollable ownership #ifndef OWNERSTACK_H #define OWNERSTACK_H template<class T> class Stack { struct Link { T* data; Link* next; Link(T* dat, Link* nxt) : data(dat), next(nxt) {} }* head; bool own; public: Stack(bool own = true) : head(0), own(own) {} ~Stack(); void push(T* dat) { head = new Link(dat,head); } T* peek() const { return head ? head->data : 0; } T* pop(); bool owns() const { return own; } void owns(bool newownership) { own = newownership; } // Auto-type conversion: true if not empty: operator bool() const { return head != 0; } }; template<class T> T* Stack<T>::pop() { if(head == 0) return 0; T* result = head->data; Link* oldHead = head; head = head->next; delete oldHead; return result; } template<class T> Stack<T>::~Stack() { if(!own) return; while(head) delete pop(); } #endif // OWNERSTACK_H ///:~ Le défaut précèdent est pour le conteneur pour détruire son objet mais vous pouvez changer cela par soit modifier le constructeur soit utiliser le droit( ) lire/écrire de la fonction membre. Comme avec le plus grand nombre de templates que vous verrez, l’implémentation entière est contenu dans le fichier d’entête. Voici un petit test comme exercice sur les capacités des droits d’utilisateur : //: C16:OwnerStackTest.cpp //{L} AutoCounter #include "AutoCounter.h" #include "OwnerStack.h" #include "../require.h" #include <iostream> #include <fstream> #include <string> using namespace std; int main() { Stack<AutoCounter> ac; // Ownership on Stack<AutoCounter> ac2(false); // Turn it off AutoCounter* ap; for(int i = 0; i < 10; i++) { ap = AutoCounter::create(); ac.push(ap); if(i % 2 == 0) ac2.push(ap); } while(ac2) cout << ac2.pop() << endl; // No destruction necessary since // ac "owns" all the objects } ///:~ L’objet ac2 n’a pas le contrôle de l’objet que vous mettez dedans, ainsi ac est le conteneur “maître” qui prend la responsabilité pour les droits d’utilisateur. Si durant une partie de la vie du conteneur, vous voulez changer de conteneur qui prend cet objet, vous pouvez utiliser l’utilisation de owns( ). Il est possible aussi de changer la granularité du droit d’utilisateur donc c’est une sorte de base d’objet par objet, mais vous pourrez probablement faire la solution du problème des droits d’utilisateur qui sera plus complexe que le problème.