2010-08-16 8 views
2

Au travail, nous avons une classe de base, appelons-la IntrusiveBase, qui agit comme un mixin pour permettre à une classe d'être stockée dans un boost: intrusive_ptr. Autrement dit, il fournit à ses sous-classes un nombre de références et définit les surcharges intrusive_ptr_add_ref et intrusive_ptr_release. Le problème est qu'il est trop facile pour quelqu'un d'oublier qu'une sous-classe particulière hérite de IntrusiveBase, et ils le stockent ensuite dans un autre pointeur intelligent comme un scoped_ptr ou shared_ptr. Cela ne fonctionne pas parce que, par exemple, le scoped_ptr va supprimer l'objet quand il sort de la portée, peu importe ce que le compte ref se trouve être. Nous avons une assertion dans ~ IntrusiveBase que le compte de ref est un, mais ce n'est pas infaillible parce que souvent il finira par n'être que l'instance d'origine au moment où le scoped_ptr sort de la portée. Cela laisse un échec insidieux qui attend de se produire ces quelques fois que le nombre de ref est pas un.Comment empêcher le stockage d'une classe intrusive_ptr dans d'autres pointeurs intelligents

Y at-il un moyen de provoquer un échec de compilation si quelqu'un le fait accidentellement? Même si je dois faire quelque chose de façon répétitive pour chacune des principales classes de pointeurs intelligents, cela en vaudrait la peine.

+0

Vous devriez probablement autoriser l'utilisation de scoped_ptr - quiconque utilisant scoped_ptr comprend probablement que ce seul bloc de code devrait posséder cette instance de la classe. –

+0

'intrusive_ptr' comme classe de base est toujours ennuyeux. Pensez à la redoutable hiérarchie de l'héritage des diamants ... C'est pourquoi 'unique_ptr',' scoped_ptr' et 'shared_ptr' sont si populaires. –

Répondre

6

Même si je dois faire quelque chose de manière répétitive pour chacune des principales classes de pointeurs intelligents, cela en vaudrait la peine.

Dans ce cas, vous pouvez les spécialiser sur vos types d'héritage InstrusiveBase.

namespace boost 
    { 
    template<> 
    class scoped_ptr<InstrusiveBaseSubclass> { }; // scoped_ptr<InstrusiveBaseSubClass> p(new InstrusiveBaseSubClass) won't compile, neither will p->, p.get() etc. 

    } 

Ceci est gênant, mais il est macro-Able, e..g:

class A : InstrusiveBase 
{ 
    ... 
} 
NO_SCOPED_PTR(A) 
NO_SHARED_PTR(A) 
5

Une autre option serait de surcharger et d'en supprimer pour ces classes et de faire supprimer privé ou protégé. instrusive_ptr_release pourrait alors devenir une fonction friend ou une technique similaire utilisée pour invoquer réellement delete lorsque le compte ref a chuté à zéro.

+0

Donc, j'ai essayé, mais cela ne semble pas fonctionner. J'ai rencontré ce problème: http://stackoverflow.com/questions/1820069/public-operator-new-private-operator-delete-getting-c2248-can-not-access-priva – SCFrench