Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

question sur l'upcast de pointeur "intelligents"

2 réponses
Avatar
Outils1
Bonjour à tous,

J'utilise une classe pour encapsuler mes pointeurs, ils s'utilisent
classiquement de la manière suivante:

ObjectPointer<BaseObject> baseptr(new BaseObject());
ObjectPointer<DeriveeObject> deriveeptr(new DeriveeObject());

mon problème c'est qu'avec cette technique je perd l'upcast automatique
lorsque je passe un pointeur à une fonction:

class CTest : public Object
{
private:
ObjectPointer<Object> ptr;

public:
CTest() :ptr() {}
CTest(ObjectPointer<Object>& object) :ptr(object) {}
};

je ne peux pas passer deriveeptr comme argument de mon deuxième constructeur
puisque les types sont incompatibles...
je peux regler mon problème en définissant mon constructeur ainsi:

template <class T> CTest(ObjectPointer<T>& object) :ptr(object) {}

Ca marche très bien, l'ennui c'est que dans mon interface, je perd
l'information que c'est un pointeur sur un Object et ses dérivées que je
veux et pas n'importe quel objet. Quelqu'un a-t-il une meilleure solution à
me proposer, une astuce, une manière différente de voir les choses ?

Merci.

2 réponses

Avatar
Loïc Joly
Outils1 wrote:
Bonjour à tous,

J'utilise une classe pour encapsuler mes pointeurs, ils s'utilisent
classiquement de la manière suivante:

ObjectPointer<BaseObject> baseptr(new BaseObject());
ObjectPointer<DeriveeObject> deriveeptr(new DeriveeObject());

mon problème c'est qu'avec cette technique je perd l'upcast automatique
lorsque je passe un pointeur à une fonction:

class CTest : public Object
{
private:
ObjectPointer<Object> ptr;

public:
CTest() :ptr() {}
CTest(ObjectPointer<Object>& object) :ptr(object) {}
};

je ne peux pas passer deriveeptr comme argument de mon deuxième constructeur
puisque les types sont incompatibles...


Tu peux peut-être (de vieux compilos peuvent poser des problèmes)
définir à ObjectPointer un constructeur templaté à ton template qui
prenne en charge les conversions. Par exemple, exemple tiré de boost :

template<class T> class shared_ptr
{
// ...
template<class Y>
shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
{
}
// ...
};


--
Loïc

Avatar
Outils1
"Loïc Joly" a écrit dans le message news:
bq5qug$4d6$
Tu peux peut-être (de vieux compilos peuvent poser des problèmes)
définir à ObjectPointer un constructeur templaté à ton template qui
prenne en charge les conversions. Par exemple, exemple tiré de boost :

template<class T> class shared_ptr
{
// ...
template<class Y>
shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never
throws

{
}
// ...
};


Effectivement, la classe ObjectPointer a bien un constructeur de copie
template, de même que l'opérateur d'affectation, mon problème ne se situe
pas au niveau de la classe ObjectPointer, mais bien au niveau de la classe
CTest. Si je reprend mon exemple:

class CTest : public Object
{
private:
ObjectPointer<Object> ptr;

public:
CTest() :ptr() {}
CTest(ObjectPointer<Object>& object) :ptr(object) {}
};


ObjectPointer<Object> baseptr(new Object());
ObjectPointer<DeriveeObject> deriveeptr(new DeriveeObject());

Ctest test1(baseptr); // est valide
Ctest test2(deriveeptr); // est interdit car ObjectPointer<Object> et
ObjectPointer<DeriveeObject> ne sont pas du même type.


J'ai résolu mon problème en passant mes pointeurs par valeur et non plus par
référence, là ca marche... Le seul hic, c'est que cela me crée un object
temporaire, ce que j'aurais voulu éviter, mais c'est précisement le
constructeur de mon pointeur temporaire qui me fait la conversion de type...