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) {}
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 ?
Le type de retour étant (std::)string, tu dois renvoyer un string.
Ce qui pourrait bien expliquer l'erreur qu'il a vu. À la site de l'appel, on va bien appeler le destructeur de la chaîne qu'il n'a jamais construite.
[...]
typedef enum MODE {DERIV1, DERIV2};
Ça compile sans warning, ça ?! Le "typedef" est ici une bizarrerie du langage C (et encore, je ne suis même pas sûr que ce soit correct). Enlève-le.
Utiliser comme ça, ça ne sert pas en C non plus. Intuitivement, j'aurais cru que c'était illégal -- le typedef ne rapporte à rien dans la déclaration. Mais je ne trouve rien dans la norme qui l'intérdit. (C'est probablement juste une oublie -- ou que personne dans le comité n'ait même pû imaginer le cas.)
-- James Kanze GABI Software 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
Fabien LE LEZ wrote:
On Sun, 22 Jan 2006 13:39:22 +0100, "C.B."
<wang_zangkun@hotmail.com>:
Le type de retour étant (std::)string, tu dois renvoyer un
string.
Ce qui pourrait bien expliquer l'erreur qu'il a vu. À la site de
l'appel, on va bien appeler le destructeur de la chaîne qu'il
n'a jamais construite.
[...]
typedef enum MODE {DERIV1, DERIV2};
Ça compile sans warning, ça ?!
Le "typedef" est ici une bizarrerie du langage C (et encore,
je ne suis même pas sûr que ce soit correct). Enlève-le.
Utiliser comme ça, ça ne sert pas en C non plus. Intuitivement,
j'aurais cru que c'était illégal -- le typedef ne rapporte à
rien dans la déclaration. Mais je ne trouve rien dans la norme
qui l'intérdit. (C'est probablement juste une oublie -- ou que
personne dans le comité n'ait même pû imaginer le cas.)
--
James Kanze GABI Software
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
Le type de retour étant (std::)string, tu dois renvoyer un string.
Ce qui pourrait bien expliquer l'erreur qu'il a vu. À la site de l'appel, on va bien appeler le destructeur de la chaîne qu'il n'a jamais construite.
[...]
typedef enum MODE {DERIV1, DERIV2};
Ça compile sans warning, ça ?! Le "typedef" est ici une bizarrerie du langage C (et encore, je ne suis même pas sûr que ce soit correct). Enlève-le.
Utiliser comme ça, ça ne sert pas en C non plus. Intuitivement, j'aurais cru que c'était illégal -- le typedef ne rapporte à rien dans la déclaration. Mais je ne trouve rien dans la norme qui l'intérdit. (C'est probablement juste une oublie -- ou que personne dans le comité n'ait même pû imaginer le cas.)
-- James Kanze GABI Software 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
Au fait, quel compilateur utilises-tu ? Il doit être bien mauvais s'il ne donne pas au moins un warning en voyant ça.
D'ailleurs, pourquoi est-ce autorisé ?
Parce qu'il fait partie d'une catégorie plus grande d'erreurs qui ne sont pas, en général, détectable. Remplace les appels à operator<<() par des appels à une autre fonction, que cette fonction appel exit() ou abort(), ou lève toujours une exception, et que toi, en tant que programmeur, tu le sais.
-- James Kanze GABI Software 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
Fabien LE LEZ wrote:
On Sun, 22 Jan 2006 13:39:22 +0100, "C.B."
<wang_zangkun@hotmail.com>:
Au fait, quel compilateur utilises-tu ? Il doit être bien
mauvais s'il ne donne pas au moins un warning en voyant ça.
D'ailleurs, pourquoi est-ce autorisé ?
Parce qu'il fait partie d'une catégorie plus grande d'erreurs
qui ne sont pas, en général, détectable. Remplace les appels à
operator<<() par des appels à une autre fonction, que cette
fonction appel exit() ou abort(), ou lève toujours une
exception, et que toi, en tant que programmeur, tu le sais.
--
James Kanze GABI Software
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
Au fait, quel compilateur utilises-tu ? Il doit être bien mauvais s'il ne donne pas au moins un warning en voyant ça.
D'ailleurs, pourquoi est-ce autorisé ?
Parce qu'il fait partie d'une catégorie plus grande d'erreurs qui ne sont pas, en général, détectable. Remplace les appels à operator<<() par des appels à une autre fonction, que cette fonction appel exit() ou abort(), ou lève toujours une exception, et que toi, en tant que programmeur, tu le sais.
-- James Kanze GABI Software 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
C.B.
Merci pour toutes vos réponses. Après correction des diverses erreurs (les méthodes qui ne renvoyaient pas de string) et la suppression de _prop qui compliquait (éventuellement) le problème (aec les constructeurs), ça marche. (avec l'héritage virtuel, et sans doute sans héritage virtuel aussi).
Sinon pour le typedef enum MODE, je pensais qu'il fallait le typedef pour qu'on puisse déclarer une variable de type MODE, mais en fait ça marche sans. C'est des restes de C (il faut un typedef en C notamment dans une struct, quand celle ci a comme membre un pointeur sur cette meme struct, par exemple pour des élts chaines).
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning pour le typedef.
a+
Merci pour toutes vos réponses. Après correction des diverses erreurs (les
méthodes qui ne renvoyaient pas de string) et la suppression de _prop qui
compliquait (éventuellement) le problème (aec les constructeurs), ça
marche. (avec l'héritage virtuel, et sans doute sans héritage virtuel
aussi).
Sinon pour le typedef enum MODE, je pensais qu'il fallait le typedef pour
qu'on puisse déclarer une variable de type MODE, mais en fait ça marche
sans. C'est des restes de C (il faut un typedef en C notamment dans une
struct, quand celle ci a comme membre un pointeur sur cette meme struct,
par exemple pour des élts chaines).
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning
pour le typedef.
Merci pour toutes vos réponses. Après correction des diverses erreurs (les méthodes qui ne renvoyaient pas de string) et la suppression de _prop qui compliquait (éventuellement) le problème (aec les constructeurs), ça marche. (avec l'héritage virtuel, et sans doute sans héritage virtuel aussi).
Sinon pour le typedef enum MODE, je pensais qu'il fallait le typedef pour qu'on puisse déclarer une variable de type MODE, mais en fait ça marche sans. C'est des restes de C (il faut un typedef en C notamment dans une struct, quand celle ci a comme membre un pointeur sur cette meme struct, par exemple pour des élts chaines).
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning pour le typedef.
a+
Fabien LE LEZ
On Mon, 23 Jan 2006 22:47:07 +0100, "C.B." :
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning pour le typedef.
Assure-toi de compiler avec l'option -Wall (affichage de tous les warnings).
On Mon, 23 Jan 2006 22:47:07 +0100, "C.B." <wang_zangkun@hotmail.com>:
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning
pour le typedef.
Assure-toi de compiler avec l'option -Wall (affichage de tous les
warnings).
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning pour le typedef.
Assure-toi de compiler avec l'option -Wall (affichage de tous les warnings).
Marc Boyer
Le 23-01-2006, Fabien LE LEZ a écrit :
On Mon, 23 Jan 2006 22:47:07 +0100, "C.B." :
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning pour le typedef.
Assure-toi de compiler avec l'option -Wall (affichage de tous les warnings).
-Wall ce n'est pas *tous les warnings* mais *beaucoup de warning*. Celui que je conseille aussi, c'est -Wuninitialized (qui nécessite -O). A titre personnel, je rajoute -pedantic -W. Je pense que tout débutant devrait faire pareil.
Marc Boyer -- Entre le fort et le faible, c'est la liberte qui opprime et le droit qui libere. Henri Lacordaire, Dominicain
Le 23-01-2006, Fabien LE LEZ <gramster@gramster.com> a écrit :
On Mon, 23 Jan 2006 22:47:07 +0100, "C.B." <wang_zangkun@hotmail.com>:
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning
pour le typedef.
Assure-toi de compiler avec l'option -Wall (affichage de tous les
warnings).
-Wall ce n'est pas *tous les warnings* mais *beaucoup de warning*.
Celui que je conseille aussi, c'est -Wuninitialized (qui nécessite -O).
A titre personnel, je rajoute -pedantic -W.
Je pense que tout débutant devrait faire pareil.
Marc Boyer
--
Entre le fort et le faible, c'est la liberte qui opprime et le droit
qui libere. Henri Lacordaire, Dominicain
Sinon je compilais avec gcc4.0.1 (sous Mandriva 2006), sans aucun warning pour le typedef.
Assure-toi de compiler avec l'option -Wall (affichage de tous les warnings).
-Wall ce n'est pas *tous les warnings* mais *beaucoup de warning*. Celui que je conseille aussi, c'est -Wuninitialized (qui nécessite -O). A titre personnel, je rajoute -pedantic -W. Je pense que tout débutant devrait faire pareil.
Marc Boyer -- Entre le fort et le faible, c'est la liberte qui opprime et le droit qui libere. Henri Lacordaire, Dominicain
Fabien LE LEZ
On Tue, 24 Jan 2006 08:12:58 +0000 (UTC), Marc Boyer :
-Wall ce n'est pas *tous les warnings* mais *beaucoup de warning*.
Bvarf. Si je comprends bien, "all" veut autant dire dire "tous" que (std::)"remove" veut dire "enlever"...
On Tue, 24 Jan 2006 08:12:58 +0000 (UTC), Marc Boyer
<Marc.Boyer@enseeiht.yahoo.fr.invalid>:
-Wall ce n'est pas *tous les warnings* mais *beaucoup de warning*.
Bvarf. Si je comprends bien, "all" veut autant dire dire "tous" que
(std::)"remove" veut dire "enlever"...