0/5 (5 avis)
Snippet vu 6 027 fois - Téléchargée 18 fois
// le fichier de base // base.h #include <stdio.h> class IObject { public: int count; Object() : count(0) {} virtual ~Object() {} friend int addRef(IObject * obj); friend int release(IObject * obj); }; int addRef(IObject * obj) { if(obj==0) return 0; return obj->count++; } int release(IObject * obj){ if (obj==0) return 0; obj->count--; if(obj->count<=0){ delete obj; return 0; } return obj->count ; } template <class T> class GsMem { public: T * obj ; GsMem(T * oobj) { if(oobj){ obj = oobj; addRef(obj); } obj = 0; } virtual ~GsMem() { release(obj); } GsMem & operator=(IObject * oobj) { if(oobj) { if (obj) { release(obj); obj = oobj ; addRef(obj); } else { obj = oobj ; addRef(obj); } else { if(release(obj)<=0) obj=0; } } }; // fichier .cpp #include "base.h" class Test : public IObject { public: int cd ; Test(int code) { cd = code ; printf("creation de l'objet %d\n",code); } virtual ~Test() { printf("destruction de l'objet %d\n",cd); } }; int main() { printf("exemple 1 : (sans utilisation du GsMem)\n"); { Test * t = new Test(1) ; } printf("exemple 2 : (utilisation du GsMem au declaration)\n"); { GsMem<Test> t = new Test(2) ; } printf("exemple 3 : (utilisation du GsMem )\n"); { Test * t = new Test(3) ; GsMem<Test> gs = t ; } return 0 ; }
5 juin 2013 à 07:02
C'est mieux que les auto_ptr d'origine du C++ mais en deça de boost.
30 mai 2013 à 19:03
Comprends-tu à quoi sert le mot clé "virtual" ? Je n'en ai pas l'impression...
Un héritage virtuel ("public virtual") n'est surtout utile qu'en cas d'héritage multiple en diamand, pour ne garder "qu'une partie de la branche" C'est une notion avancée, peu utilisé.
Je critiquais la simple présence d'héritage dynamique, qui n'a rien à faire dans ce genre de code...
29 mai 2013 à 01:19
que peut tu me dit si je mis " class Test : public virtual IObject {... "
28 mai 2013 à 18:49
Je déconseille fortement l'utilisation de cette source ! Je la laisse à titre d'exemple.
Il y a plusieurs soucis:
Techniquement:
- Le mot clé "friend" est à éviter. C'est généralement signe d'une mauvaise conception. Ici on aurait pu largement s'en passer, au profit de deux méthodes statiques. (voir même comme de simples méthodes membres, vu ce que tu en fais).
- Plutôt que de faire: "if (obj==0) return 0;", lever une assertion aurait été bien plus judicieux. Ici tu masques une erreur.
- L'obligation de devoir hériter d'une classe, force la création d'une vtable juste pour cela. Or, niveau performance, ce n'est pas forcément terrible. Utiliser des templates aurait permis d'avoir ce genre de fonctionnalité, sans l'obligation du coût caché par un polymorphisme (dès le moment ou tu as un seul virtual, tu auras une table virtuelle...)
- On différencie une variable locale d'un attribut via un signe distinctif. On utilise généralement "_". On devrait donc avoir: T* obj => T* _obj;
Architecture:
L'architecture n'est pas terrible. Utiliser la classe "IObject" seule, conduit à des fuites de mémoires. Normalement, une seule classe devrait suffire.
Soit tu fais une classe "intrusive", comme les "boost::intrusive_ptr", auquel cas ta classe hérite (de préférence statiquement) d'un compteur partagé entre les différentes instances du même type, soit tu donnes l'intégralité de la réponsabilité à une classe dédiée (comme les std::shared_ptr). Avoir deux classes qui ont chacunes une partie de la reponsabilité est vraiment peu élégant et source d'erreurs.
Principe:
Sur le principe, tu as essayé de refaire en (beaucoup) moins bien, un système de smart pointer. Je conseille à ceux qui liront de plutôt utiliser:
- boost::intrusive_ptr
- boost::shared_ptr ou std::shared_ptr
- boost::weak_ptr ou std::weak_ptr
- std::unique_ptr
28 mai 2013 à 17:17
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.