2010-04-21 11 views
2

J'ai implémenté des pointeurs de comptage de référence (appelés SP dans l'exemple) et j'ai des problèmes de polymorphisme que je ne devrais pas avoir.Pointeurs intelligents et polymorphisme

Dans le code suivant:

SP<BaseClass> foo() 
    { 
     // Some logic... 
     SP<DerivedClass> retPtr = new DerivedClass(); 
     return retPtr; 
    } 

DerivedClass hérite de BaseClass. Avec des pointeurs normaux cela aurait dû fonctionner, mais avec les pointeurs intelligents, il est écrit "cannot convert from 'SP<T>' to 'const SP<T>&" et je pense qu'il fait référence au constructeur de copie du pointeur intelligent.

Comment autoriser ce type de polymorphisme avec un pointeur de comptage de référence? J'apprécierais que les exemples de code provoquent évidemment quelque chose d'incorrect ici si j'ai ce problème.

PS: Veuillez ne pas me dire d'utiliser une bibliothèque standard avec des pointeurs intelligents, car c'est impossible pour le moment.

+0

Veuillez indiquer le code du constructeur de copie. – Danvil

+0

Lors de la lecture des messages d'erreur de modèle, il est important de noter ce que le «T» signifie dans chaque position. L'erreur a probablement dit quelque chose comme ne peut pas convertir de 'SP avec [T = DerivedClass] à const SP & avec [T = BaseClass]' cette information supplémentaire est la moitié du chemin de la solution. –

Répondre

6

assez évident:

SP<DerivedClass> retPtr = new DerivedClass(); 

devrait être:

SP<BaseClass> retPtr = new DerivedClass(); 
+2

La conversion de SP en SP ne devrait poser aucun problème avec une bonne implémentation de pointeur intelligent. – Danvil

+0

Cela résout le problème spécifique dans 'foo()', mais cela ne crée pas de syntaxe naturelle dans d'autres endroits où la conversion peut être nécessaire. – Gorpik

+1

@Danvil: La conversion n'est pas le problème, vous ne pouvez pas changer le type de retour dans une fonction surchargée sauf dans des cas limités (références covariantes et pointeurs), il est inutile de créer même un SP du mauvais type. Cette réponse est la plus simple: créer un objet du type retourné. –

0

Pourquoi ne pas ajouter un opérateur d'affectation de modèle:

template <class Base> 
class SP 
{ 
    ... 

    template<class Derived> 
    operator = (SP<Derived>& rhs) 
    { 
     ... 

(et peut-être copier constructeur, aussi)?

4

Vous devez ajouter constructeur conversion implicite SP<T>:

template<class T> 
struct SP { 
    /// ...... 
    template<class Y> 
    SP(SP <Y> const & r) 
    : px(r.px) // ... 
    { 
    } 

    //.... 
private: 
    T * px; 
} 
+0

Un constructeur de modèle n'est jamais un constructeur de copie. Un constructeur de copie ne va pas aider; c'est un constructeur de conversion non-explicite. –

+0

@Charles. Droite. Peu importe. –

0

En plus du constructeur de copie:

SP(const SP<T>& ref); 

vous avez besoin d'un constructeur de conversion:

template<typename T2> 
SP(const SP<T2>& ref); 

Dans le cas contraire, la compilateur ne saura pas comment construire SP<BaseClass> à partir d'un SP<DerivedClass>; pour lui, ils ne sont pas liés.

Le constructeur de conversion est assez trivial, puisque vous pouvez convertir en interne *DerivedClass en *BaseClass automatiquement. Le code peut être très similaire à celui du constructeur de copie.