OVH Cloud OVH Cloud

mutation d'instance (héritage multiple)

23 réponses
Avatar
C.B.
Bonjour,
voici mon problème (extrait d'un exam) (utilisant de l'héritage multiple)

J'ai une classe de Base, et deux classes Deriv1 et Deriv2 qui en dérivent.
Ces deux classes Deriv1 et Deriv2 ont des propriétés distinctes, modélisées
ici juste par un attribut _prop (string) de la classe Base, et les méthodes
getProp() des deux classes (qui affichent de quelle classe Deriv1 ou Deriv2
elles sont appelées, et affichent ensuite prop).

J'ai une classe Deriv1Et2 qui dérive de Deriv1 et Deriv2. Je veux que cette
classe ait tantot les propriétés de Deriv1, tantot les propriétés de
Deriv2. On utilise pour cela un type enuméré MODE, et la méthode mutation()
qui va changer de mode. Ensuite, dans la méthode getProp de Deriv1Et2,
suivant le mode, j'appelle Deriv1::getProp() et Deriv2::getProp().

Ceci pour modéliser la mutation d'instance : si Deriv1Et2 a les propriétés
de Deriv1, j'appelle mutation(), elle a les propriétés de Deriv2.
(j'espère etre assez clair, mais le pb est assez compliqué a saisir)

Voici le code, qui compile sans erreurs :

/******** testVirtual.cpp

#include <iostream>
#include <string>
using namespace std;

class Base {
protected:
string _prop;
public:
Base() : _prop("") {}
Base(string p) : _prop(p) {}
};

class Deriv1 : virtual public Base {
public:
Deriv1() { _prop = ""; }
Deriv1(string p) : Base(p) {}

virtual string getProp();
};

string Deriv1::getProp() {
cout << "props de Deriv1 : " << _prop;
}

class Deriv2 : virtual public Base {
public:
Deriv2() { _prop = ""; }
Deriv2(string p) : Base(p) {}

virtual string getProp();
};

string Deriv2::getProp() {
cout << "props de Deriv2 : " << _prop;
}

typedef enum MODE {DERIV1, DERIV2};

class Deriv1Et2 : public Deriv1, public Deriv2 {
private:
MODE _m;
public:
Deriv1Et2() : _m(DERIV1) {}
Deriv1Et2(string p) : Deriv1(p), _m(DERIV1) {}

virtual string getProp();
void mutation();
};

void Deriv1Et2::mutation() {
if (_m == DERIV1) { _m = DERIV2; } else { _m = DERIV1; }
}

string Deriv1Et2::getProp() {
if (_m == DERIV1) {
Deriv1::getProp();
}
else {
Deriv2::getProp();
}
}

int main(int argc, char** argv) {
Deriv1Et2 d1;
Deriv1Et2 d2("Mes props");

cout << "au départ : " << endl
<< "d1 : " << d1.getProp() << endl
<< "d2 : " << d2.getProp() << endl;

d1.mutation();
d2.mutation();

cout << "après mutation 1 : " << endl
<< "d1 : " << d1.getProp() << endl
<< "d2 : " << d2.getProp() << endl;

d1.mutation();
d2.mutation();

cout << "après mutation 2 : " << endl
<< "d1 : " << d1.getProp() << endl
<< "d2 : " << d2.getProp() << endl;
}

***************************/

Et voici le résultat que j'obtiens :
*** glibc detected *** free(): invalid pointer: 0xb7e7afe8 ***
props de Deriv1 : Abandon

En changeant l'héritage virtuel des classes Deriv1 et Deriv2 et héritage
normal, j'obtiens :
*** glibc detected *** free(): invalid pointer: 0xb7dfefe8 ***
props de Deriv1 : Mes propsAbandon

Ici l'affiche de _prop se passe bien (mais ça ne marche toujours pas).
Quelqu'un aurait une piste, une idée ?

Merci d'avance

3 réponses

1 2 3
Avatar
Gabriel Dos Reis
"kanze" writes:

[...]

| En passant, je trouve la forme -std=c++98 particulièrement bien
| conçue. Après tout, comme j'ai lu dans un .sig quelque part,
| «@The nice thing about standards is that there are so many to
| chose from. » Alors, on précise le parfum du jour. Ça deviendra
| particulièrement interessant quand il y aura une nouvelle
| version de C++, avec peut-être quelques petites incompatibilités
| avec l'ancienne. Alors, -std=c++98 pour l'ancien code,
| -std=c++0x pour le nouveau.

oui, c'est déjà le cas pour C, ou nous avons -stdÈ9 et -stdÉ9

[...]

| > > Ça date, et je ne me rappelle plus des avertissements idiots
| > > à l'époque, mais il y en a bien aujourd'hui. Y compris
| > > certains que je ne sais pas supprimer, genre « vous vous
| > > êtes servi de tmpnam, ce n'est pas bien » (or que c'est bien
| > > LA fonction qu'il faut, dans le contexte où je l'utilise).
|
| > Ça c'est le linker, pas GCC.
|
| Il sort lors de la compilation, si je me souviens correctement.
|
| En revanche, il ne sort que sous Linux ;

Tu as raison sur un point: C'est une combinaison de GNU ld et glibc.
GNU ld support la section "warning", alord glibc lui demande d'émettre
un warning lorsque le symbole est utilisé.

http://lists.gnu.org/archive/html/bug-binutils/2004-07/msg00071.html

Cela m'a frustré la première fois que je l'ai eu en compilant Axiom
mais bon, pas outre mesure.

-- Gaby
Avatar
Jean-Marc Bourguet
Gabriel Dos Reis writes:

Tu as raison sur un point: C'est une combinaison de GNU ld et glibc.
GNU ld support la section "warning", alord glibc lui demande d'émettre
un warning lorsque le symbole est utilisé.


Est-ce qu'il y a moyen de lui demander de se taire?

Les warnings, c'est bien tant qu'on peut les controler. Quand on ne
peut pas...

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Gabriel Dos Reis
Jean-Marc Bourguet writes:

| Gabriel Dos Reis writes:
|
| > Tu as raison sur un point: C'est une combinaison de GNU ld et glibc.
| > GNU ld support la section "warning", alord glibc lui demande d'émettre
| > un warning lorsque le symbole est utilisé.
|
| Est-ce qu'il y a moyen de lui demander de se taire?

Je ne sais pas s'il support l'équivalent de -Wno-xxx ou -w.

| Les warnings, c'est bien tant qu'on peut les controler. Quand on ne
| peut pas...


Yup.

-- Gaby
1 2 3