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

Problèmes d'héritage

32 réponses
Avatar
No_Name
Bonjour,

Je travaille sur une application en C++ pour laquelle j'ai plusieurs
niveaux d'héritage :

A = Classe mère
Classe B = Hérite de A
Classe C = Hérite de B

Je voudrais pouvoir facilement transformer des objets de type B en
objets de type C et inversément.

Pour passer de C à B, j'imagine qu'un simple cast suffira, sachant
qu'en faisant cela, je perdrai les données qui font la sécificité de C
(puisque le but est de me retrouver avec un objet de type B).

Par contre, je ne vois pas bien comment je peux passer de B à C ?
J'envisageais de doter la classe C d'une fonction permettant de créer
un objet de type C à partir d'un objet de type B, en initialisant les
données supplémentaires à des valeurs par défaut, mais je ne suis pas
complètement sur de cette solution.

Et les fonctions de création d'un objet de type B en objet de type C
doivent elle effectivement être des méthodes de la classe C ?

Merci de vos conseils et suggestions.

2 réponses

1 2 3 4
Avatar
James Kanze
On Jan 27, 3:56 pm, (Pascal J. Bourguignon)
wrote:
No_Name writes:
> Fabien LE LEZ a utilisé son clavier pour écrire :
>> On Tue, 27 Jan 2009 14:31:26 +0100, No_Name :



>>> Parce que le new() que j'utilise pour créer mon objet me
>>> retourne un pointeur ...



>> Mais typiquement, ce que new renvoie, on le stocke dans un
>> pointeur intelligent, pour éviter les fuites mémoire.



>> (Je dis "typiquement", car certains objets se détruisent
>> tout seuls.)



>> Et question subsidiaire : pourquoi new est-il utilisé ici ?
>> Au moins dans le cadre de ce thread, ça ne fait que
>> compliquer le problème. Cherche d'abord à bien comprendre
>> les mécanismes de passage entre B et C avec des objets
>> normaux, et ensuite seulement, tu pourras ajouter, si
>> nécessaire, les complications liées à l'allocation
>> dynamique.



> En effet, mais la question que je posais s'inscrivait dans
> un véritable projet. Il ne s'agit pas d'un exercice de
> style, et il me faut bien adapter les réponses qui m'ont été
> faites à la réalité de mon code.



> Merci encore pour vos réponses qui m'ont permis de régler le
> problème.



Le problème est que si le code utilise new pour créer des
objets, il s'attend certainement à avoir une sémantique
d'identité, pas de valeur.



Peut-être dans le code que tu écris, et certainement dans le
code que j'écris, mais il y a bien des programmeurs qui viennent
de Java, et qui n'ont pas compris la règle. Alors, si je suis
bien d'accord avec le principe que tu énonces, je crois que sa
formulation confond le but et les moyens : ce n'est pas
l'allocation dynamique qui impose la sémantique d'identité ;
c'est la sémantique d'identité qui motive l'allocation
dynamique. Qui ne doit servir que si elle est bien motivée.

Sinon, il n'y aurait que des C c; B b; et des copies de
valeurs: b=c;



Dans l'ensemble, la polymorphisme et l'affectation se marient
mal ; c'est extrèmement rare d'avoir une classe avec des
fonctions virtuelles qui supporte l'affectation. Précisement
parce que la sémantique d'affectation dans ce cas-là imposerait
un changement de type d'un objet, ce qui est impossible en C++
(et aussi en Java, et je crois aussi en SmallTalk -- peut-être
en Lisp ?). Quand l'application exige et une sémantique de valeur
et le polymorphisme (ce qui est assez rare d'après mon
expérience), on est obligé à se retourner vers des choses comme
l'idiome lettre-enveloppe, avec toute la complexité que ça
impose.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
James Kanze
On Jan 27, 1:01 pm, (Pascal J. Bourguignon)
wrote:
No_Name writes:



[...]
Normalement, en OO, un objet a une identité.



Pour la plupart des définitions d'OO, oui. Qu'on a affaire à
l'OO ici, ça reste à voir.

C'est une dépravation de C++ d'appeler "objet" des valeurs que
l'on copie ou projette n'importe comment,



Non, c'est simplement une utilisation d'un vocabulaire plus
général, non propre à l'OO. Je me rappelle plus qui l'a dit,
mais le C++ n'est pas un langage OO, c'est un langage polyvalent
qui permet de faire le OO. L'utilisation du mot « objet » en
C++, c'est hérité de C, et n'a rien à voir avec l'OO.

Maintenant, si son but est de faire des objets polymorphiques,
selon les théories de l'OO, il est mal barré si l'objet supporte
l'affectation. Mais ce n'est pas encore établi. Je veux savoir
ce que ces objets représentent réelement. J'ai prèsque
l'impression qu'il utilise plutôt une technique de mixin pour
des objets à valeur. Dans tel cas, évidemment, l'héritage est
pûrement de l'implémentation, et doit probablement être privé,
mais il reste à voir. Des noms du genre A, B et C ne me dit pas
long sur la sémantique attendue.

est c'est aussi un grand risque de bogues.



C c;
B b=c; // dépravé!



Ça dépend. Si C est double, et B int, et qu'on a vérifié avant
que c a une valeur entière (ou qu'on veut sa valeur arrondie
vers 0), c'est parfaitement OK. Si ces classes sont des valeurs
(non des objets polymorphiques), et une conversion entre les
types a un sens, il n'y a pas de problème.

Mais j'avoue que dans l'ensemble, je préfère les conversions
explicites. Sauf cas exceptionnel, quelque chose du genre :

C c ;
B b = c.toB() ;

C'est quand même plus clair pour celui qui lit le code.

Par contre quand on réfère les objets via des pointeurs, on
est vraiment OO, et tout fonctionne bien:



C* c=new C;
B* b=c; // no problem.



Dans ce cas, b et c réfèrent le MÊME objet.



Qui a toujours le type C.

Normalement, cela n'a de sens *que* si l'objet est polymorphique
et que B a des fonctions virtuelles. Ce qui fait que le type
statique et le type dynamique ne sont pas forcément le même.

Ça permet de travailler avec un objet d'une sous-classe de B
sans savoir à priori de quelle sous-classe il s'agit (en
utilisant les méthodes virtual, toutes les méthodes devraient
être virtual, sinon c'est un signe de dépravation!),



Là, tu divagues. Il n'y a que des cas spéciaux (inversion de
l'appel, par exemple) où une fonction publique doit être
virtuelle. Normalement, il n'y a que des fonctions privées (ou
protégé, selon la théorie) qui sont virtuelles. Le fait de
rendre une fonction virtuelle représente une perte de contrôle,
qu'il faut bien gérer.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
1 2 3 4