OVH Cloud OVH Cloud

référence et constructeur par défaut...

5 réponses
Avatar
Simon Lipp
Bonjour,

Je dois actuellement modifier un gros programme, dont l'auteur a disparu
dans la nature...
Pour l'instant, mon but est de réussir à le porter (Windows->Linux) sans
trop de casse (cad ne me dites pas de revoir complètement l'architecture
générale, je le ferais, mais plus tard, quand j'aurais à peu près compris
comment ça marche ;))
Ca passe impec, sauf un petit problème avec G++ qui ne veut pas compiler
quelque chose qu'apparement Visual C++ acceptait. J'en ai fait un simple
résumé sur le code source suivant:

class Padawan {
public:
Padawan() { }
};

class Instructor {
Padawan& m_bizut;

public:
Instructor(Padawan& p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
Jedi(): Instructor(Padawan()) { }
};

En gros, j'aimerais donner class Padawan {
public:
Padawan() { }
};

class Instructor {
Padawan& m_bizut;

public:
Instructor(Padawan& p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
Jedi(): Instructor(Padawan()) { }
};

Quelqu'un aurait il une idée un peu plus belle que remplacer
Jedi(): Instructor(Padawan()) { }
par
Jedi(): Instructor(*(new Padawan)) { }
pour le faire compiler par G++ ? (parce ma méthode, en plus d'être moche,
donne des fuites de mémoire)
Si vous réussissez à me donner une piste (autre que "recode tout"), je vous
en serait éternellement reconnaissant

Merci d'avance ;)

5 réponses

Avatar
Marc Boyer
Le 17-05-2006, Simon Lipp a écrit :
Bonjour,

Je dois actuellement modifier un gros programme, dont l'auteur a disparu
dans la nature...
Pour l'instant, mon but est de réussir à le porter (Windows->Linux) sans
trop de casse (cad ne me dites pas de revoir complètement l'architecture
générale, je le ferais, mais plus tard, quand j'aurais à peu près compris
comment ça marche ;))
Ca passe impec, sauf un petit problème avec G++ qui ne veut pas compiler
quelque chose qu'apparement Visual C++ acceptait. J'en ai fait un simple
résumé sur le code source suivant:

class Padawan {
public:
Padawan() { }
};

class Instructor {
Padawan& m_bizut;


Pourquoi donc ?
James t'en parlera mieux que moi, mais avoir des références
membres est si j'ai bien retenu une mauvaise idée en général.
Il y a des problèmes sur les opérations de copie, ce
genre de chose.
D'autant que là, tu cherches à avoir une référence sur un
temporaire.
Donc, choisi ton camps: Padawan ou Padawan*.

Si vous réussissez à me donner une piste (autre que "recode tout"), je vous
en serait éternellement reconnaissant


--------- Version Padawan (composition en UML) -----
class Padawan {
public:
Padawan() { }
};

class Instructor {
Padawan m_bizut;

public:
Instructor(const Padawan& p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
Jedi(): Instructor(Padawan()) { }
};

--------- Version Padawan* (aggrégation en UML) -----
class Padawan {
public:
Padawan() { }
};

class Instructor {
Padawan* m_bizut;

public:
Instructor(Padawan* p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
Jedi(): Instructor( new Padawan()) { }
};


Les deux compilent (avec mon g++ (GCC) 4.0.2),
mais la sémantique de la relation est différente.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)

Avatar
Simon Lipp
  D'autant que là, tu cherches à avoir une référence sur un
temporaire.
J'ai bien compris que le problème venait d'ici ;)


  Donc, choisi ton camps: Padawan ou Padawan*.
Comme je l'ai dit, le programme est déjà fait. Je choisirais mon camps quand

il tournera et que je pourrais tester si mes modifications font tout
planter ou pas - quand je pourrait vraiment debugger, là je suis seulement
dans la phase le faire compiler. Si je modifie trop de trucs avant de
tester si ça marche, je pourrais pas savoir ce qui a tout pété. Je n'ai, à
l'heure actuelle, aucun moyen de mesurer les conséquences du changement de
Padawan& et Padawan ou Padawan...

--------- Version Padawan (composition en UML) -----
class Padawan {
public:
        Padawan() { }
};

class Instructor {
        Padawan m_bizut;

public:
        Instructor(const Padawan& p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
        Jedi(): Instructor(Padawan()) { }
};

Très bien. Supposons que Instructor aie à modifier Padawan. Jedi s'en

contrefout, mais on peut imaginer une fonction de ce type:
void instruct(Padawan& p) {
        Instructor i(p);
        i.learn_mathematics(); // modifie p
}
Avec la version Padawan&, pas de problème, le padawan connaitra les maths.
Avec la version Padawan, aucune chance...

--------- Version Padawan* (aggrégation en UML) -----
class Padawan {
public:
  Padawan() { }
};

class Instructor {
  Padawan* m_bizut;

public:
  Instructor(Padawan* p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
        Jedi(): Instructor( new Padawan()) { }
};
Oui, mais dans ce cas, qui doit détruire m_bizut ?

Ca ne peut être Instructor: la plupart du temps, p était une référence (donc
maintenant un pointeur) sur une variable locale. Si Instructor le détruit,
je vais me taper des segfault qui viendront de je ne sais trop où ;)
Comme c'est une variable locale, je pourrais me dire que pas besoin de la
détruire. Mais le problème, c'est alors le
        Jedi(): Instructor( new Padawan()) { }
qui me donnera une belle fuite de mémoire...


Bon, vivement que ça tourne, que je puisse modifier tout ça ;)

PS: désolé d'avoir répondu par mail, je me suis planté d'icone (j'aime pas
akregator ;))

Avatar
Marc Boyer
Le 18-05-2006, Simon Lipp a écrit :
  Donc, choisi ton camps: Padawan ou Padawan*.
Comme je l'ai dit, le programme est déjà fait. Je choisirais mon camps quand

il tournera et que je pourrais tester si mes modifications font tout
planter ou pas - quand je pourrait vraiment debugger, là je suis seulement
dans la phase le faire compiler. Si je modifie trop de trucs avant de
tester si ça marche, je pourrais pas savoir ce qui a tout pété. Je n'ai, à
l'heure actuelle, aucun moyen de mesurer les conséquences du changement de
Padawan& et Padawan ou Padawan...


Sans rien savoir du contexte, je miserais plutôt
sur un Padawan*.

--------- Version Padawan (composition en UML) -----
class Padawan {
public:
        Padawan() { }
};

class Instructor {
        Padawan m_bizut;

public:
        Instructor(const Padawan& p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
        Jedi(): Instructor(Padawan()) { }
};

Très bien. Supposons que Instructor aie à modifier Padawan. Jedi s'en

contrefout, mais on peut imaginer une fonction de ce type:
void instruct(Padawan& p) {
        Instructor i(p);
        i.learn_mathematics(); // modifie p
}
Avec la version Padawan&, pas de problème, le padawan connaitra les maths.
Avec la version Padawan, aucune chance...


Avec la version Padawan*, il les connaitra aussi.

--------- Version Padawan* (aggrégation en UML) -----
class Padawan {
public:
  Padawan() { }
};

class Instructor {
  Padawan* m_bizut;

public:
  Instructor(Padawan* p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
        Jedi(): Instructor( new Padawan()) { }
};
Oui, mais dans ce cas, qui doit détruire m_bizut ?



Ben, celui qui le construit, c'est à dire Jedi.

~Jedi(){
delete m_bizut;
}

Bon, vivement que ça tourne, que je puisse modifier tout ça ;)

PS: désolé d'avoir répondu par mail, je me suis planté d'icone (j'aime pas
akregator ;))


Tant pis pour toi: j'ai une adresse .invalid.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)


Avatar
Marc Duflot
Simon Lipp wrote:
class Padawan {
public:
Padawan() { }
};

class Instructor {
Padawan& m_bizut;

public:
Instructor(Padawan& p): m_bizut(p) { }
};

class Jedi: protected Instructor {
public:
Jedi(): Instructor(Padawan()) { }
};

Quelqu'un aurait il une idée un peu plus belle que remplacer
Jedi(): Instructor(Padawan()) { }
par
Jedi(): Instructor(*(new Padawan)) { }
pour le faire compiler par G++ ? (parce ma méthode, en plus d'être moche,
donne des fuites de mémoire)


Ce n'est pas propre mais si tu n'es autorisé qu'à modifier Jedi, tu peux
t'en sortir avec un héritage privé :

class Jedi: private Padawan, protected Instructor {
public:
Jedi(): Instructor((Padawan&)*this) { }
};

Avatar
Simon Lipp
Oui, mais dans ce cas, qui doit détruire m_bizut ?
Ben, celui qui le construit, c'est à dire Jedi.

Ya des jours où je me sens bête, et ya des jours tout les jours, comme

dirait l'autre ;)
On va mettre ça sur le compte d'une accumulation de fatigue et de stress,
hein ;) (non, je n'ai pas bu...)

Bon, je vais faire comme ça, merci beaucoup :)