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

Caster un objet en un autre objet

14 réponses
Avatar
Korchkidu
Bonjour,

j'ai une classe de base BaseClass et N classe d=E9riv=E9es DerClass1,
DerClass2, etc. Mon programme travaille sur un std::vector<BaseClass*>
et j'ai besoin de pouvoir facilement changer n'importe quel DerClass_i
en n'importe quel autre DerClass_j =E0 l'=E9x=E9cution du programme. Une
solution pourrait =EAtre d'impl=E9menter tous les cast possible mais du
coup, =E0 chaque fois que je rajoute une DerClass, =E7a me fait beaucoup
de boulot en plus car je dois =E9crire tous les cast possibles. Sinon,
je peux isoler la partie qui change d'une DerClass =E0 l'autre et en
faire une classe SubClass pour chaque DerClass. Ensuite, chaque
DerCLass contiendra un pointeur sur le bon SubClass et lorsque je dois
changer le type de DerClass, je d=E9truit le pointeur de SubClass et
j'en recr=E9=E9 un qui =E0 le bon type.

Quelles sont vos suggestions compte-tenu de votre (longue)
exp=E9rience ?

D'avance merci pour votre aide.
K.

10 réponses

1 2
Avatar
pjb
Korchkidu writes:

Bonjour,

j'ai une classe de base BaseClass et N classe dérivées DerClass1,
DerClass2, etc. Mon programme travaille sur un std::vector<BaseClass*>
et j'ai besoin de pouvoir facilement changer n'importe quel DerClass_i
en n'importe quel autre DerClass_j à l'éxécution du programme. Une
solution pourrait être d'implémenter tous les cast possible mais du
coup, à chaque fois que je rajoute une DerClass, ça me fait beaucoup
de boulot en plus car je dois écrire tous les cast possibles. Sinon,
je peux isoler la partie qui change d'une DerClass à l'autre et en
faire une classe SubClass pour chaque DerClass. Ensuite, chaque
DerCLass contiendra un pointeur sur le bon SubClass et lorsque je dois
changer le type de DerClass, je détruit le pointeur de SubClass et
j'en recréé un qui à le bon type.

Quelles sont vos suggestions compte-tenu de votre (longue)
expérience ?



Implémente le "state design pattern" aka "strategy design pattern" aka
"policy design pattern". En deux mots, ne change pas la classe de
l'objet en question, mais change un objet avec lequel il est en
relation, et surlequel il se base pour adapter son comportement.




[Bien sur, l'alternative supersimple, c'est d'utiliser CLOS où les
objets peuvent changer de classe comme on veut avec:
(change-class instance 'nouvelle-class)
mais c'est HS ici... Enfin pas tant que ça. Des MOP ont été
implémentés pour C++, par exemple:
http://www.csg.is.titech.ac.jp/~chiba/openc++.html
donc il devrait être possible d'implémenter un système objet où
changeClass est possible. (Notez que le MOP OpenC++ contient une
méthode changeBaseClasses pour les meta classes).]

--
__Pascal Bourguignon__
Avatar
Michael Doubez
On 23 juil, 12:42, Korchkidu wrote:
j'ai une classe de base BaseClass et N classe dérivées DerClass1,
DerClass2, etc. Mon programme travaille sur un std::vector<BaseClass*>
et j'ai besoin de pouvoir facilement changer n'importe quel DerClass_i
en n'importe quel autre DerClass_j à l'éxécution du programme.



Tu veux changer le type d'une instance ou remplacer un élément de ton
tableau ?


Une
solution pourrait être d'implémenter tous les cast possible mais du
coup, à chaque fois que je rajoute une DerClass, ça me fait beaucoup
de boulot en plus car je dois écrire tous les cast possibles. Sinon,
je peux isoler la partie qui change d'une DerClass à l'autre et en
faire une classe SubClass pour chaque DerClass.



Si tu peux faire ça, est ce que tu ne peux pas avoir une classe
intermédiaire DerClass qui met en commun les éléments qui ne changent
pas entre DerClass_x.

class DerClass: public BaseClass
{
// interface commune
}

// puis pour chaque sous classe
class DerClass_n: public DerClass
{
DerClass_n(const DerClass& d):DerClass(d){}

};
// ...

Ensuite, tu peux faire
BaseClass tableau[42];

DerClass* derclass=static_cast<DerClass*>(tableau[i]);
DerClass_k n = new DerClass_k(*derclass);
tableau[i]=n;
delete derclass;

Ensuite, chaque
DerCLass contiendra un pointeur sur le bon SubClass et lorsque je dois
changer le type de DerClass, je détruit le pointeur de SubClass et
j'en recréé un qui à le bon type.



Le détruire, ça veut dire que tu n'en a pas besoin pour initialiser la
nouvelle instance ?

Si ce que tu veux ne doit pas modifier le tableau, donc ce que tu veux
est transtyper les instances. Pour ça il n'y a que le polymorphisme
dynamique (qui est de la forme comme tu viens de le décrire: changer
une pointeur interne).

Quelles sont vos suggestions compte-tenu de votre (longue)
expérience ?



Sans connaitre ce que tu veux faire au niveau des fonctionnalités, je
préfère ne rien suggérer.

--
Michael
Avatar
Korchkidu
On Jul 23, 2:04 pm, (Pascal J. Bourguignon)
wrote:
Implémente le "state design pattern" aka "strategy design pattern" aka
"policy design pattern".  En deux mots, ne change pas la classe de
l'objet en question, mais change un objet avec lequel il est en
relation, et surlequel il se base pour adapter son comportement.

[Bien sur, l'alternative supersimple, c'est d'utiliser CLOS où les
 objets peuvent changer de classe comme on veut avec:
   (change-class instance 'nouvelle-class)
 mais c'est HS ici... Enfin pas tant que ça.  Des MOP ont été
 implémentés pour C++, par exemple:
   http://www.csg.is.titech.ac.jp/~chiba/openc++.html
 donc il devrait être possible d'implémenter un système objet o ù
 changeClass est possible. (Notez que le MOP OpenC++  contient une
 méthode changeBaseClasses pour les meta classes).]


Merci beaucoup pour votre réponse. Je vais regarder ce que ce design
pattern fait.

Meilleures salutations.
K.
Avatar
Korchkidu
On Jul 23, 2:19 pm, Michael Doubez wrote:
Tu veux changer le type d'une instance ou remplacer un élément de ton
tableau ?


Non, il faut changer le type de l'instance.

Si tu peux faire ça, est ce que tu ne peux pas avoir une classe
intermédiaire DerClass qui met en commun les éléments qui ne change nt
pas entre DerClass_x.


Oui, c'est la solution que je proposais mais je n'ai pas été très
clair, je l'avoue^^
> Ensuite, chaque
> DerCLass contiendra un pointeur sur le bon SubClass et lorsque je dois
> changer le type de DerClass, je détruit le pointeur de SubClass et
> j'en recréé un qui à le bon type.

Le détruire, ça veut dire que tu n'en a pas besoin pour initialiser l a
nouvelle instance ?


Oups, tu as raison. Il faut inverse les étapes car oui, j'ai besoin de
l'ancienne instance pour initialiser la nouvelle.


Merci beaucoup pour ton aide.
K.
Avatar
Michael Doubez
On 23 juil, 14:04, (Pascal J. Bourguignon)
wrote:
Korchkidu writes:
> Bonjour,

> j'ai une classe de base BaseClass et N classe dérivées DerClass1,
> DerClass2, etc. Mon programme travaille sur un std::vector<BaseClass*>
> et j'ai besoin de pouvoir facilement changer n'importe quel DerClass_i
> en n'importe quel autre DerClass_j à l'éxécution du programme. Un e
> solution pourrait être d'implémenter tous les cast possible mais du
> coup, à chaque fois que je rajoute une DerClass, ça me fait beaucou p
> de boulot en plus car je dois écrire tous les cast possibles. Sinon,
> je peux isoler la partie qui change d'une DerClass à l'autre et en
> faire une classe SubClass pour chaque DerClass. Ensuite, chaque
> DerCLass contiendra un pointeur sur le bon SubClass et lorsque je dois
> changer le type de DerClass, je détruit le pointeur de SubClass et
> j'en recréé un qui à le bon type.

> Quelles sont vos suggestions compte-tenu de votre (longue)
> expérience ?

Implémente le "state design pattern" aka "strategy design pattern" aka
"policy design pattern".



Pour être précis, le "state pattern" et le "strategy pattern" sont
proches mais ne répondent pas aux même besoins:
- le state pattern: permet de modifier l'état interne et son
comportement (donc le type en POO)
- le strategy pattern: ne modifie que le comportement (i.e. la
fonctionnalité reste la même aux décorations près) - typiquement un
changement d'algorithm ou insertion d'actions avant ou après un algo.

 En deux mots, ne change pas la classe de
l'objet en question, mais change un objet avec lequel il est en
relation, et surlequel il se base pour adapter son comportement.



C'est sûr que qui peut le plus peut le moins mais, AMA, il n'en dit
pas assez pour savoir si c'est la seule solution. L'héritage simple
est quand même plus facile.

[snip]
--
Michael
Avatar
Michael Doubez
On 23 juil, 14:29, Korchkidu wrote:
On Jul 23, 2:19 pm, Michael Doubez wrote:> Tu veux changer le type d'une instance ou remplacer un élément de ton
> tableau ?

Non, il faut changer le type de l'instance.



Ok. Dans ce cas, le choix est réduit: c'est plutôt la solution que tu
proposais (composition avec un type polymorphique).

> Si tu peux faire ça, est ce que tu ne peux pas avoir une classe
> intermédiaire DerClass qui met en commun les éléments qui ne chan gent
> pas entre DerClass_x.

Oui, c'est la solution que je proposais mais je n'ai pas été très
clair, je l'avoue^^



Si, tu as été clair mais je pensais à l'héritage simple: BaseClass <-
DerClass <- DerClass_x.

Mais si c'est le type de l'instance qui doit changer, alors la
question n'a plus lieu d'être.

Tu pourrais alors utiliser un vector<DerClass> plutôt que un
vector<BaseClass*>.

> > Ensuite, chaque
> > DerCLass contiendra un pointeur sur le bon SubClass et lorsque je doi s
> > changer le type de DerClass, je détruit le pointeur de SubClass et
> > j'en recréé un qui à le bon type.

> Le détruire, ça veut dire que tu n'en a pas besoin pour initialiser la
> nouvelle instance ?

Oups, tu as raison. Il faut inverse les étapes car oui, j'ai besoin de
l'ancienne instance pour initialiser la nouvelle.



Tu veux dire que l'état interne SubClass de l'instance sert à
initialiser le nouveau SubClass ?

Dans ce cas, ne seras tu pas obligé de coder les fonctions de
transtypage ?

--
Michael
Avatar
Korchkidu
On Jul 23, 2:43 pm, Michael Doubez wrote:

Tu veux dire que l'état interne SubClass de l'instance sert à
initialiser le nouveau SubClass ?

Dans ce cas, ne seras tu pas obligé de coder les fonctions de
transtypage ?



Je ne pense pas. Il suffit. au changement d'état, de faire moi même la
conversion et d'appeler le constructeur du nouvelle état avec les bon
arguments. Ça devrait marcher comme ça je pense non ?

K.
Avatar
Michael Doubez
On 23 juil, 14:50, Korchkidu wrote:
On Jul 23, 2:43 pm, Michael Doubez wrote:

> Tu veux dire que l'état interne SubClass de l'instance sert à
> initialiser le nouveau SubClass ?

> Dans ce cas, ne seras tu pas obligé de coder les fonctions de
> transtypage ?

Je ne pense pas. Il suffit. au changement d'état, de faire moi même l a
conversion et d'appeler le constructeur du nouvelle état avec les bon
arguments. Ça devrait marcher comme ça je pense non ?



C'est toi qui sais.

Mais tu vas avoir quelquechose du genre:

struct SubClass
{
virtual ~SubClass();

virtual void foo()=0;
}:

struct DerClass
{
void foo(){ state->foo(); }

std::auto_ptr<SubClass> state;
};

DerClass instance;
instance.state.reset(new SubClass_1(42));
instance.foo();

Si tu veux construire un SubClass_2 à partir de SubClass_1, il faut
bien que tu aies une fonction de conversion / de dispatch:
instance.state.reset(new SubClass_2( ??? ) );

--
Michael
Avatar
Benoit
On Jul 23, 3:48 pm, Michael Doubez wrote:
On 23 juil, 14:50, Korchkidu wrote:

> On Jul 23, 2:43 pm, Michael Doubez wrote:

> > Tu veux dire que l'état interne SubClass de l'instance sert à
> > initialiser le nouveau SubClass ?

> > Dans ce cas, ne seras tu pas obligé de coder les fonctions de
> > transtypage ?

> Je ne pense pas. Il suffit. au changement d'état, de faire moi même la
> conversion et d'appeler le constructeur du nouvelle état avec les bon
> arguments. Ça devrait marcher comme ça je pense non ?

C'est toi qui sais.

Mais tu vas avoir quelquechose du genre:

struct SubClass
{
    virtual ~SubClass();

    virtual void foo()=0;

}:

struct DerClass
{
    void foo(){ state->foo(); }

    std::auto_ptr<SubClass> state;

};

DerClass instance;
instance.state.reset(new SubClass_1(42));
instance.foo();

Si tu veux construire un SubClass_2 à partir de SubClass_1, il faut
bien que tu aies une fonction de conversion / de dispatch:
instance.state.reset(new SubClass_2( ??? ) );


Oui, effectivement. Donc soit je le fais "à la main" en ne tenant
compte que des infos utiles pour passer de l'un à l'autre, soit je
fais des fonctions de conversion de SubClass_1 vers SubClass_2 ainsi
que toutes les autres... Je vais réfléchir plus longuement à tout ç a.
Merci beaucoup pour votre aide. Ca me permet d'avancer un peu plus. Je
repasserai sans doute par là d'ici peu...;-)

Meilleures salutations.
K.
Avatar
Korchkidu
> Si tu veux construire un SubClass_2 à partir de SubClass_1, il faut
bien que tu aies une fonction de conversion / de dispatch:
instance.state.reset(new SubClass_2( ??? ) );



Oui, effectivement. Donc soit je le fais "à la main" en ne tenant
compte que des infos utiles pour passer de l'un à l'autre, soit je
fais des fonctions de conversion de SubClass_1 vers SubClass_2 ainsi
que toutes les autres... Je vais réfléchir plus longuement à tout ç a.
Merci beaucoup pour votre aide. Ça me permet d'avancer un peu plus. Je
repasserai sans doute par là d'ici peu...;-)

Meilleures salutations.
K.
1 2