Le code avec lequel je travaille a sa propre implémentation de pointeur intelligent qui effectue un simple comptage de références. Oui, nous ne devrions pas avoir notre propre implémentation. Oui, nous devrions utiliser un boost ou un autre. Ours avec moi.Problèmes lors de l'écriture d'un constructeur de copie pour un pointeur intelligent
Je trouve que je voulais écrire du code comme ceci:
...
CountedPointer<Base> base;
...
CountedPointer<Derived> derived;
...
base = derived;
Cependant, le constructeur de copie pour CountedPointer a un prototype comme celui-ci:
CountedPointer(const CountedPointer<T> &other);
Ainsi, le code ci-dessus ne sera pas compilé depuis il ne peut pas trouver un constructeur approprié (ou un opérateur d'affectation - c'est la même histoire là). J'ai essayé de réécrire le constructeur de copie avec un prototype comme celui-ci:
template<U>
CountedPointer(const CountedPointer<U> &other);
Cependant, je frappe le problème que le constructeur de copie doit accéder à un membre privé de l'objet qu'elle copie (par exemple le pointeur brut) et si elle est dans une spécialisation différente de CountedPointer, ils ne sont pas visibles. Alexandrascu évite ce problème dans sa bibliothèque Loki en ayant des fonctions d'accesseur pour le pointeur encapsulé, mais je préférerais ne pas donner un accès direct au pointeur brut si possible.
Y at-il un moyen que je peux écrire cela pour permettre la dérivée à la copie de base, mais ne permet pas l'accès général au pointeur brut?
Mise à jour: J'ai implémenté la réponse acceptée ci-dessous, et cela fonctionne bien. J'ai passé un moment à comprendre pourquoi mon programme se trompait terriblement lorsque je ne fournissais que la version du constructeur de copie, en remplacement de la version originale non-modélisée. Finalement, je me suis rendu compte que le compilateur ne considère pas la version modélisée comme étant un constructeur de copie, et en fournit un par défaut. Celui par défaut copie simplement le contenu sans mettre à jour le compteur, donc je me retrouve avec des pointeurs pendants et des doubles libres. Le même genre de chose s'applique à l'opérateur d'affectation.
Il est assez difficile d'empêcher l'accès au pointeur brut. & * CounterPointer() est généralement un T * brut. Ne fonctionne pas bien avec les pointeurs null cependant. –
MSalters
Je me sens comme fournir une fonction dans l'interface suggère que l'utilisation du pointeur brut est une bonne idée. Si quelqu'un décide qu'il doit aller au pointeur brut, il modifiera l'interface de toute façon. C'est plutôt mineur. Si c'était mon code, ça ne me dérangerait pas trop. – Ned