OVH Cloud OVH Cloud

héritage ou nouvelle classe?

46 réponses
Avatar
Zoubidaman
Bonsoir,

j'ai une classe Possessions:

class Possessions
{
private:
//Le début et la fin d'une pause
typedef pair<int,int> Pauses;

//La liste des pauses
typedef vector<Pauses> ListePauses;
typedef ListePauses::iterator ite_Pauses;
ListePauses LP;

int __fastcall DureePause();
public:
int DebutPossession,FinPossession;
AnsiString ActiondeFin;
TColor CouleurActiondeFin;

Possessions();

Possessions(
int DebutPossession,
int FinPossession,
const ListePauses & VecteurPauses,
AnsiString ActiondeFin,
TColor CouleurActiondeFin)
:
DebutPossession(DebutPossession),
FinPossession(FinPossession),
LP(VecteurPauses),
ActiondeFin(ActiondeFin),
CouleurActiondeFin(CouleurActiondeFin)
{}

const ListePauses & AccesListePauses() const { return this->LP; }

int __fastcall DureePossession();
};

J'ai besoin d'une classe Strategies, qui ait la même partie private, mais
avec la partie publique différente, car j'ai besoin de moins de
variables...

Comme je ne connais (pour l'instant) rien à l'héritage, je voulais savoir
si j'avais besoin de passer par là, ou bien s'il fallait que je crée une
nouvelle classe...

Merci d'avance...

10 réponses

1 2 3 4 5
Avatar
Vivien Gallinaro
Zoubidaman wrote:

Néanmoins j'ai tenté de faire avec l'héritage, et j'en suis là:


Si on passe le fait qu'il a été démontré que par composition, ça passe
bien, il y a quelques trucs qui ne vont pas avec le code que tu as
donné, et qui en empêchent la compilation.

class Base
{
private:
ListePauses LP;
// ...
};

class Possessions : Base
{
public:
Possessions( /*...*/ ) : LP(VecteurPauses), /*...*/ {}
// ...
};


Quand tu écris "class Possessions : Base { /*...*/ };" tu définis Base
comme une base private de Possessions (1), c'est à dire que les membres
de Posessions ne peuvent manipuler que les membres publics de Base.

(1) Il faudrait que je vérifie, mais si l'héritage était public par
défaut, je ne pense pas qu'on l'écrirait à chaque fois ;)

Et à la compilation, il me met une erreur à LP(VecteurPauses)...

Message d'erreur de Builder:

'Base::LP' n'est pas une classe de base non ambiguë de 'Possessions'


Le message n'aide pas beaucoup, effectivement. Mais LP étant membre
privé de Base, le constructeur ne le connaît pas, et donc ne peut pas
l'initialiser. La façon de l'initialiser, c'est d'avoir un constructeur
(publique) de Base qui prend un objet du type de VecteurPauses pour
initialiser LP. A ce moment, tu peux écrire ton constructeur :

Possessions ( /*...*/ ) : Base (VecteurPauses), /*...*/ {}

[ Attention à l'ordre : les initialisations de classes de base doivent
se trouver avant celles des membres... C'est pourquoi je ne comprends
pas bien que ton compilo pense avoir à faire à un nom de classe de base
alors qu'il a déjà initialisé des membres. L'ordre serait-il moins
important que je ne le crois ? Ou c'est l'écriture qui est tolérée avec
un résultat plus ou moins garanti ? ]

L'autre possibilité, c'est évidemment d'hériter en publique :

class Possessions : public Base { /*...*/ };

Cela dit, j'imagine qu'un héritage private est plus approprié --- outre
le fait, encore une fois, que ça a l'air de mieux marcher avec la
composition.

A part ça, comme le disait Fabien, nommer les paramètres du constructeur
exactement comme les membres est un truc que je n'essayerait pas.
Peut-être que ça marche, mais c'est pas très lisible...

Gourgouilloult du Clapotis

Avatar
Fabien LE LEZ
On Wed, 13 Aug 2003 07:59:17 +0200, Julien Blanc
wrote:

En fait, il me parait beaucoup plus sage d'encapsuler les méthodes au
moins dans un namespace.


Qu'appelles-tu "méthodes", exactement ?


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Fabien LE LEZ
On Wed, 13 Aug 2003 12:44:22 +0200, Vivien Gallinaro
wrote:

nommer les paramètres du constructeur
exactement comme les membres est un truc que je n'essayerait pas.

Peut-être que ça marche,


Je confirme que ça ne marche pas, je me suis fait avoir une fois ^^


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Loïc Joly
Christophe Lephay wrote:
"Vivien Gallinaro" a écrit dans le
message de news:

[ Attention à l'ordre : les initialisations de classes de base doivent
se trouver avant celles des membres... C'est pourquoi je ne comprends
pas bien que ton compilo pense avoir à faire à un nom de classe de base
alors qu'il a déjà initialisé des membres. L'ordre serait-il moins
important que je ne le crois ? Ou c'est l'écriture qui est tolérée avec
un résultat plus ou moins garanti ? ]



Il me semble bien (je ne sais pas ce que dit la norme précisément) que tu
peux écrire les initialisations dans l'ordre que tu veux, elles seront
néanmoins effectuées dans l'ordre des déclaration (alors autant les
initialiser dans le même ordre, ça peut éviter certaines confusions comme
d'utiliser un membre pour en initialiser un autre en le croyant valide alors
qu'il ne l'est pas encore)...



Effectivement, et c'est assez logique :

Si les membres étaient initialisés dans l'ordre où ils apparaissent dans
la liste d'initialisation, ça voudrait dire que deux constructeurs
pourraient initialiser les membres dans un ordre différent.

Or, une règle de base du C++ est de détruire dans l'ordre inverse de la
création, donc pour respecter ça, et comme une classe n'a qu'un seul
destructeur, il faudrait garder trace de quel constructeur a construit
l'objet courant pour savoir dans quel ordre le détruite, et ce serait :
- Pas efficace
- Le bordel

--
Loïc


Avatar
Alain Naigeon
"Loïc Joly" a écrit dans le message news:
bhe410$709$


Si les membres étaient initialisés dans l'ordre où ils apparaissent dans
la liste d'initialisation, ça voudrait dire que deux constructeurs
pourraient initialiser les membres dans un ordre différent.

Or, une règle de base du C++ est de détruire dans l'ordre inverse de la
création, donc pour respecter ça, et comme une classe n'a qu'un seul
destructeur, il faudrait garder trace de quel constructeur a construit
l'objet courant pour savoir dans quel ordre le détruite, et ce serait :
- Pas efficace
- Le bordel


Ouah, chapeau pour le raisonnement !
(ce qui est bien, c'est qu'en sachant le pourquoi des choses,
on les retient sans effort - bravo et merci !)

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France

Avatar
drkm
Fabien LE LEZ writes:

On Wed, 13 Aug 2003 12:44:22 +0200, Vivien Gallinaro
wrote:

nommer les paramètres du constructeur exactement comme les membres
est un truc que je n'essayerait pas.

Peut-être que ça marche,


Je confirme que ça ne marche pas, je me suis fait avoir une fois ^^


Tiens. Je me suis amusé il n'y a pas longtemps avec « log4cplus »,
et si je me souviens bien, l'auteur utilisait la même technique. Qui
m'a d'ailleurs déroutée (que c'est laid !). Mais il me semble que
cela compilait sans diagnostique avec « g++ -Wall -ansi -pedantic »,
même si je sais que cela ne signifie pas grand-chose.

Qu'en est-il, finalement ? Quelqu'un connait-il les chapitres et
versets, par curiosité ?

--drkm


Avatar
Fabien LE LEZ
On Wed, 13 Aug 2003 17:37:59 +0200, Fabien LE LEZ
wrote:

Je confirme que ça ne marche pas, je me suis fait avoir une fois ^^


Euh... en fait, si, vu qu'une variable locale a priorité sur une
variable "moins locale" de même nom :

struct C
{
int i, j;
C (int i, int j)
: i /* C'est une initialisation, donc il ne peut s'agir que de
la variable membre [*] */
(i) /* Ici, il y a ambiguïté -- et c'est la variable locale qui
l'emporte. Donc ça fait bien ce qu'on veut */
{
j= j; /* Ceci, par contre, est une affectation, pas une
initialisation. Par conséquent, c'est la variable locale qui est
désignée ici (à gauche et à droite) -- et cette ligne est une no-op.
Mais si quelqu'un vient me dire que c'est une justification pour
écrire systématiquement "this->" devant les variables membres, je ne
réponds plus de rien ;-) */
}
};

[*] Pas 100 % sûr de moi sur ce coup-là. De toutes façons c'est une
écriture à éviter absolument.


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
drkm
Gabriel Dos Reis writes:

drkm writes:

| Fabien LE LEZ writes:

| > On Wed, 13 Aug 2003 12:44:22 +0200, Vivien Gallinaro
| > wrote:

| Tiens. Je me suis amusé il n'y a pas longtemps avec
| « log4cplus », et si je me souviens bien, l'auteur utilisait la
| même technique. Qui m'a d'ailleurs déroutée (que c'est laid !).
| Mais il me semble que cela compilait sans diagnostique avec « g++
| -Wall -ansi -pedantic », même si je sais que cela ne signifie pas
| grand-chose.

struct point {
double x, y;
point(double x, double y) : x(x), y(y) { }
};

est bien défini et doit faire La Bonne Chose.


Au niveau technique. Mais je pense que cela relève plus de
l'obfuscation qu'autre chose.

| Qu'en est-il, finalement ? Quelqu'un connait-il les chapitres
| et versets, par curiosité ?

regarde dans le chaptre name lookup (désolé, je ne suis pas au bon
endroit).


Merci.

--drkm

Avatar
Gabriel Dos Reis
drkm writes:

| Gabriel Dos Reis writes:
|
| > drkm writes:
|
| > | Fabien LE LEZ writes:
|
| > | > On Wed, 13 Aug 2003 12:44:22 +0200, Vivien Gallinaro
| > | > wrote:
|
| > | Tiens. Je me suis amusé il n'y a pas longtemps avec
| > | « log4cplus », et si je me souviens bien, l'auteur utilisait la
| > | même technique. Qui m'a d'ailleurs déroutée (que c'est laid !).
| > | Mais il me semble que cela compilait sans diagnostique avec « g++
| > | -Wall -ansi -pedantic », même si je sais que cela ne signifie pas
| > | grand-chose.
|
| > struct point {
| > double x, y;
| > point(double x, double y) : x(x), y(y) { }
| > };
|
| > est bien défini et doit faire La Bonne Chose.
|
| Au niveau technique. Mais je pense que cela relève plus de
| l'obfuscation qu'autre chose.

Ne voulais-tu pas une réponse au niveau technique ?

-- Gaby
Avatar
drkm
Gabriel Dos Reis writes:

drkm writes:

| Au niveau technique. Mais je pense que cela relève plus de
| l'obfuscation qu'autre chose.

Ne voulais-tu pas une réponse au niveau technique ?


Si. L'ayant eue, je pouvais alors aporter une précision à un autre
niveau.

--drkm

1 2 3 4 5