Bonjour à tous, je développe un petit projet en C++ et je bute sur
l'utilisation du conteneur associatif «std::map».
Voici un résumé de ma structure:
///////////////////////////////////////////////////////
/* Une classe à dériver, car la fonction membre
«Acheter» fournit les éléments soit d'un objet externe
défini par «Achalander» soit construits directement dans la classe
dérivée.
*/
class cEtalage
{
std::vector<std::string> xPanier;
public:
cEtalage();
virtual ~cFruits();
bool virtual Acheter(
unsigned int n,
const std::string& produit,
void **panier);
};
class cFruits:cEtalage
{
public:
cFruits();
virtual ~cFruits();
Achalander(ProducteurDeFruits *camion);
bool virtual Acheter(
unsigned int n,
const std::string& produit,
void **panier);
}
class cLegumes:cEtalage
{
public:
cLegumes();
virtual ~cLegumes();
Achalander(ProducteurDeLegumes *camion);
bool virtual Acheter(unsigned int n, const std::string& produit, void
**panier);
La dernière ligne provoque sous VC++6 un message d'erreur du type :
«impossible d'attacher MesFruits car des fonctions membres existent mais
sont inaccessibles».
Je l'écris de mémoire, je n'ai plus le compilateur et le code sous la main.
Veuillez m'en excuser.
Comment devrais-je construire ce conteneur, afin qu'il me permette
d'utiliser des classes dérivées de cEtalage ?
Dans le même domaine, puis-je directement dériver le constructeur de la
classe cEtalage dans les classes dérivées ?
Ex : cFruits::cFruits(ProducteurDeFruits *camion);
cLegumes::cLegumes(ProducteurDeLegumes *camion);
De la même manière, si j'ai une classe de type
class cFournissseur{
class cFournissseur(const std::string Adresse);
class ~cFournissseur();
}
et que j'en range les objets dans un
std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair(
"Toto",cFournisseur("square Georges Brassens")));
est détruit juste derrière après son insertion.
Comment créer un conteneur de ce type, dans un «for» par exemple, sans
faire appel à «new» et aux pointeurs?
Quelque chose a du m'échapper dans le principe de fonctionnement des
«map» , ces problèmes sont surement liés à la même erreur.
Ce n'est pas tout à fait la même chose, mais ça donne la même erreur.
Fabien LE LEZ
On Tue, 10 Aug 2004 20:59:52 +0200, David MAREC :
class cEtalage { public: virtual ~cFruits();
Erreur ici : le destructeur doit s'appeler "~cEtalage()". Maintenant, as-tu besoin d'un destructeur ? Il doit bien sûr exister pour pouvoir être virtuel, mais généralement il n'a pas besoin de contenir d'instructions :
J'imagine que tu t'es assuré que la durée de vie de "MesFruits" est au moins égale à celle de MonPanier ?
et que j'en range les objets dans un std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair( "Toto",cFournisseur("square Georges Brassens"))); est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais tout va bien, car map<>::insertt() en fait une copie. Ça ne serait bien sûr pas le cas si tu écrivais std::map<std::string, cFournisseur*>
-- ;-)
On Tue, 10 Aug 2004 20:59:52 +0200, David MAREC
<dmarec.spam@spambox.invalid>:
class cEtalage
{
public:
virtual ~cFruits();
Erreur ici : le destructeur doit s'appeler "~cEtalage()".
Maintenant, as-tu besoin d'un destructeur ? Il doit bien sûr exister
pour pouvoir être virtuel, mais généralement il n'a pas besoin de
contenir d'instructions :
J'imagine que tu t'es assuré que la durée de vie de "MesFruits" est au
moins égale à celle de MonPanier ?
et que j'en range les objets dans un
std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair(
"Toto",cFournisseur("square Georges Brassens")));
est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais
tout va bien, car map<>::insertt() en fait une copie.
Ça ne serait bien sûr pas le cas si tu écrivais
std::map<std::string, cFournisseur*>
Erreur ici : le destructeur doit s'appeler "~cEtalage()". Maintenant, as-tu besoin d'un destructeur ? Il doit bien sûr exister pour pouvoir être virtuel, mais généralement il n'a pas besoin de contenir d'instructions :
J'imagine que tu t'es assuré que la durée de vie de "MesFruits" est au moins égale à celle de MonPanier ?
et que j'en range les objets dans un std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair( "Toto",cFournisseur("square Georges Brassens"))); est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais tout va bien, car map<>::insertt() en fait une copie. Ça ne serait bien sûr pas le cas si tu écrivais std::map<std::string, cFournisseur*>
-- ;-)
David MAREC
Bonjour,
Fabien LE LEZ :
class cEtalage { public: virtual ~cFruits();
Erreur ici : le destructeur doit s'appeler "~cEtalage()".
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir corrigée avant l'expédition de l'article.
Maintenant, as-tu besoin d'un destructeur ? Il doit bien sûr exister pour pouvoir être virtuel, mais généralement il n'a pas besoin de contenir d'instructions :
Pour l'une des classes dérivée, oui. Elle devra effectuer des opérations de <fermeture> ou du moins les vérifier.
J'imagine que tu t'es assuré que la durée de vie de "MesFruits" est au moins égale à celle de MonPanier ?
Oui et le problème n'apparait plus ce matin ! Tout ceci compile désormais, une facétie de VC++ sans doute. Ca m'a juste fait perdre une demi-journée cette histoire.
et que j'en range les objets dans un std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair( "Toto",cFournisseur("square Georges Brassens"))); est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais tout va bien, car map<>::insertt() en fait une copie. Ça ne serait bien sûr pas le cas si tu écrivais std::map<std::string, cFournisseur*>
C'est bien ce que je pensais, ce mécanisme de copie n'est pas du tout adapté à la classe que je stocke.Cela provoque des anomalies dans le fonctionnement du système.
Merci de vos réponses.
Bonjour,
Fabien LE LEZ :
class cEtalage
{
public:
virtual ~cFruits();
Erreur ici : le destructeur doit s'appeler "~cEtalage()".
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir corrigée
avant l'expédition de l'article.
Maintenant, as-tu besoin d'un destructeur ? Il doit bien sûr exister
pour pouvoir être virtuel, mais généralement il n'a pas besoin de
contenir d'instructions :
Pour l'une des classes dérivée, oui. Elle devra effectuer des opérations
de <fermeture> ou du moins les vérifier.
J'imagine que tu t'es assuré que la durée de vie de "MesFruits" est au
moins égale à celle de MonPanier ?
Oui et le problème n'apparait plus ce matin !
Tout ceci compile désormais, une facétie de VC++ sans doute.
Ca m'a juste fait perdre une demi-journée cette histoire.
et que j'en range les objets dans un
std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair(
"Toto",cFournisseur("square Georges Brassens")));
est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais
tout va bien, car map<>::insertt() en fait une copie.
Ça ne serait bien sûr pas le cas si tu écrivais
std::map<std::string, cFournisseur*>
C'est bien ce que je pensais, ce mécanisme de copie n'est pas du tout
adapté à la classe que je stocke.Cela provoque des anomalies dans le
fonctionnement du système.
Erreur ici : le destructeur doit s'appeler "~cEtalage()".
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir corrigée avant l'expédition de l'article.
Maintenant, as-tu besoin d'un destructeur ? Il doit bien sûr exister pour pouvoir être virtuel, mais généralement il n'a pas besoin de contenir d'instructions :
Pour l'une des classes dérivée, oui. Elle devra effectuer des opérations de <fermeture> ou du moins les vérifier.
J'imagine que tu t'es assuré que la durée de vie de "MesFruits" est au moins égale à celle de MonPanier ?
Oui et le problème n'apparait plus ce matin ! Tout ceci compile désormais, une facétie de VC++ sans doute. Ca m'a juste fait perdre une demi-journée cette histoire.
et que j'en range les objets dans un std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair( "Toto",cFournisseur("square Georges Brassens"))); est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais tout va bien, car map<>::insertt() en fait une copie. Ça ne serait bien sûr pas le cas si tu écrivais std::map<std::string, cFournisseur*>
C'est bien ce que je pensais, ce mécanisme de copie n'est pas du tout adapté à la classe que je stocke.Cela provoque des anomalies dans le fonctionnement du système.
Merci de vos réponses.
Michel Michaud
Dans news:4119e4b6$0$22029$, David
[...] Oui, c'est une faute de doigts. [...]
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir [...]
Oui et le problème n'apparait plus ce matin ! Tout ceci compile désormais, une facétie de VC++ sans doute.
Très très peu probable. Tu dois avoir fait une faute de doigt encore une fois... Il ne faut jamais blâmé le compilateur avant d'avoir vérifié, revérifié, rerevérifié, rererevérifié ton code¹. Sinon tu auras toujours beaucoup plus de difficultés lors du déboguage de tes programmes, car tu penseras trop rapidement que ce n'est pas ta faute. Il y a des bogues dans les compilateurs moyens, mais même le programmeur le plus expérimenté en fait beaucoup plus régulièrement !
Ca m'a juste fait perdre une demi-journée cette histoire.
Alors prends quelques minutes pour trouver ce que tu as vraiment fait... Ce sera du temps bien investi.
¹ Et encore, ce sera bon de vérifier encore quelques fois :-)
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Dans news:4119e4b6$0$22029$626a14ce@news.free.fr, David
[...]
Oui, c'est une faute de doigts.
[...]
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir
[...]
Oui et le problème n'apparait plus ce matin !
Tout ceci compile désormais, une facétie de VC++ sans doute.
Très très peu probable. Tu dois avoir fait une faute de doigt
encore une fois... Il ne faut jamais blâmé le compilateur
avant d'avoir vérifié, revérifié, rerevérifié, rererevérifié
ton code¹. Sinon tu auras toujours beaucoup plus de difficultés
lors du déboguage de tes programmes, car tu penseras trop
rapidement que ce n'est pas ta faute. Il y a des bogues dans
les compilateurs moyens, mais même le programmeur le plus
expérimenté en fait beaucoup plus régulièrement !
Ca m'a juste fait perdre une demi-journée cette histoire.
Alors prends quelques minutes pour trouver ce que tu as
vraiment fait... Ce sera du temps bien investi.
¹ Et encore, ce sera bon de vérifier encore quelques fois :-)
--
Michel Michaud mm@gdzid.com
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir [...]
Oui et le problème n'apparait plus ce matin ! Tout ceci compile désormais, une facétie de VC++ sans doute.
Très très peu probable. Tu dois avoir fait une faute de doigt encore une fois... Il ne faut jamais blâmé le compilateur avant d'avoir vérifié, revérifié, rerevérifié, rererevérifié ton code¹. Sinon tu auras toujours beaucoup plus de difficultés lors du déboguage de tes programmes, car tu penseras trop rapidement que ce n'est pas ta faute. Il y a des bogues dans les compilateurs moyens, mais même le programmeur le plus expérimenté en fait beaucoup plus régulièrement !
Ca m'a juste fait perdre une demi-journée cette histoire.
Alors prends quelques minutes pour trouver ce que tu as vraiment fait... Ce sera du temps bien investi.
¹ Et encore, ce sera bon de vérifier encore quelques fois :-)
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
David MAREC
Bonsoir, D'après Michel Michaud:
[...] Oui, c'est une faute de doigts. [...]
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir [...]
Oui et le problème n'apparait plus ce matin ! Tout ceci compile désormais, une facétie de VC++ sans doute.
Très très peu probable. Tu dois avoir fait une faute de doigt encore une fois...
Les fautes de doigts précédentes sont dues à un autre logiciel facétieux, le tout nouveau Xorg: <news://411a5e08$0$29674$ Il n'est pas facile d'écrire quoi que ce soit dans ces conditions. :-)
Par contre, le code était identique, du moins _je_ n'ai pas fait la moindre modification entre la veille et le matin.
Il ne faut jamais blâmé le compilateur avant d'avoir vérifié, revérifié, rerevérifié, rererevérifié ton code¹.
Bah, une demi-journée pour re-re-re-vérifier cette structure quasiment vide (nettoyée de la majorité des lignes de code pour identifier l'erreur), je trouve que c'est beaucoup, sans parler de la soirée passée à relire le livre du maitre.¹
Je devrais surtout rebooter entre chaque plantage de VC++. (Le processus de compilation se bloque de temps à autres.)
Il y a des bogues dans les compilateurs moyens, mais même le programmeur le plus expérimenté en fait beaucoup plus régulièrement !
Certes, mais dans le cas présent, j'ai perdu du temps parce que je n'ai _pas_ mis en doute le compilateur.
J'aurais du l'essayer avec gcc. J'y penserais dès que je saurais m'en servir. :-)
¹ Je vous laisse imaginer ma tête lorsque, ayant mandé la compilation par pur réflexe après l'ouverture du projet, j'ai lu qu'elle s'était terminée sans erreur.
Bonsoir,
D'après Michel Michaud:
[...]
Oui, c'est une faute de doigts.
[...]
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir
[...]
Oui et le problème n'apparait plus ce matin !
Tout ceci compile désormais, une facétie de VC++ sans doute.
Très très peu probable. Tu dois avoir fait une faute de doigt
encore une fois...
Les fautes de doigts précédentes sont dues à un autre logiciel facétieux, le
tout nouveau Xorg:
<news://411a5e08$0$29674$636a15ce@news.free.fr>
Il n'est pas facile d'écrire quoi que ce soit dans ces conditions. :-)
Par contre, le code était identique, du moins _je_ n'ai pas fait la moindre
modification entre la veille et le matin.
Il ne faut jamais blâmé le compilateur
avant d'avoir vérifié, revérifié, rerevérifié, rererevérifié
ton code¹.
Bah, une demi-journée pour re-re-re-vérifier cette structure quasiment vide
(nettoyée de la majorité des lignes de code pour identifier l'erreur), je
trouve que c'est beaucoup, sans parler de la soirée passée à relire le
livre du maitre.¹
Je devrais surtout rebooter entre chaque plantage de VC++.
(Le processus de compilation se bloque de temps à autres.)
Il y a des bogues dans les compilateurs moyens,
mais même le programmeur le plus expérimenté
en fait beaucoup plus régulièrement !
Certes, mais dans le cas présent, j'ai perdu du temps parce que je n'ai
_pas_ mis en doute le compilateur.
J'aurais du l'essayer avec gcc. J'y penserais dès que je saurais m'en
servir. :-)
¹ Je vous laisse imaginer ma tête lorsque, ayant mandé la compilation par
pur réflexe après l'ouverture du projet, j'ai lu qu'elle s'était terminée
sans erreur.
Grmbl, encore une faute de doigt que j'étais persuadé d'avoir [...]
Oui et le problème n'apparait plus ce matin ! Tout ceci compile désormais, une facétie de VC++ sans doute.
Très très peu probable. Tu dois avoir fait une faute de doigt encore une fois...
Les fautes de doigts précédentes sont dues à un autre logiciel facétieux, le tout nouveau Xorg: <news://411a5e08$0$29674$ Il n'est pas facile d'écrire quoi que ce soit dans ces conditions. :-)
Par contre, le code était identique, du moins _je_ n'ai pas fait la moindre modification entre la veille et le matin.
Il ne faut jamais blâmé le compilateur avant d'avoir vérifié, revérifié, rerevérifié, rererevérifié ton code¹.
Bah, une demi-journée pour re-re-re-vérifier cette structure quasiment vide (nettoyée de la majorité des lignes de code pour identifier l'erreur), je trouve que c'est beaucoup, sans parler de la soirée passée à relire le livre du maitre.¹
Je devrais surtout rebooter entre chaque plantage de VC++. (Le processus de compilation se bloque de temps à autres.)
Il y a des bogues dans les compilateurs moyens, mais même le programmeur le plus expérimenté en fait beaucoup plus régulièrement !
Certes, mais dans le cas présent, j'ai perdu du temps parce que je n'ai _pas_ mis en doute le compilateur.
J'aurais du l'essayer avec gcc. J'y penserais dès que je saurais m'en servir. :-)
¹ Je vous laisse imaginer ma tête lorsque, ayant mandé la compilation par pur réflexe après l'ouverture du projet, j'ai lu qu'elle s'était terminée sans erreur.
David MAREC
Bonsoir. D'après Fabien LE LEZ:
et que j'en range les objets dans un std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair( "Toto",cFournisseur("square Georges Brassens"))); est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais tout va bien, car map<>::insertt() en fait une copie.
Si je comprend bien, l'objet temporaire va bel et bien être détruit par tous les mécanismes idoines (~objet()) et la copie sera aussi créée en appliquant les mécanismes associés (objet()) ?
Ça ne serait bien sûr pas le cas si tu écrivais std::map<std::string, cFournisseur*>
Pour être plus précis, l'objet qui est utilisé dans le «std::map<std::string, Objet>» va s'attacher plusieurs fils d'exécution lors de sa création.
Donc, mis à part l'utilisation d'un pointeur dans le conteneur ou de modifier la classe afin d'en séparer les processus 'embarassants' de la création, existe-t-il un mécanisme qui éviterait cet objet temporaire ?
Bonsoir.
D'après Fabien LE LEZ:
et que j'en range les objets dans un
std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair(
"Toto",cFournisseur("square Georges Brassens")));
est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais
tout va bien, car map<>::insertt() en fait une copie.
Si je comprend bien, l'objet temporaire va bel et bien être détruit par tous
les mécanismes idoines (~objet()) et la copie sera aussi créée en
appliquant les mécanismes associés (objet()) ?
Ça ne serait bien sûr pas le cas si tu écrivais
std::map<std::string, cFournisseur*>
Pour être plus précis, l'objet qui est utilisé dans le
«std::map<std::string, Objet>» va s'attacher plusieurs fils d'exécution lors
de sa création.
Donc, mis à part l'utilisation d'un pointeur dans le conteneur ou de
modifier la classe afin d'en séparer les processus 'embarassants' de la
création, existe-t-il un mécanisme qui éviterait cet objet temporaire ?
et que j'en range les objets dans un std::map<std::string, cFournisseur> xCarnet
l'objet créé par un xCarnet.insert(std::make_pair( "Toto",cFournisseur("square Georges Brassens"))); est détruit juste derrière après son insertion.
L'objet de classe "cFournisseur" est effectivement temporaire, mais tout va bien, car map<>::insertt() en fait une copie.
Si je comprend bien, l'objet temporaire va bel et bien être détruit par tous les mécanismes idoines (~objet()) et la copie sera aussi créée en appliquant les mécanismes associés (objet()) ?
Ça ne serait bien sûr pas le cas si tu écrivais std::map<std::string, cFournisseur*>
Pour être plus précis, l'objet qui est utilisé dans le «std::map<std::string, Objet>» va s'attacher plusieurs fils d'exécution lors de sa création.
Donc, mis à part l'utilisation d'un pointeur dans le conteneur ou de modifier la classe afin d'en séparer les processus 'embarassants' de la création, existe-t-il un mécanisme qui éviterait cet objet temporaire ?
Fabien LE LEZ
On Wed, 11 Aug 2004 22:42:47 +0200, David MAREC :
Si je comprend bien, l'objet temporaire va bel et bien être détruit par tous les mécanismes idoines (~objet()) et la copie sera aussi créée en appliquant les mécanismes associés (objet()) ?
Simplifions un peu le code :
std::vector<cFournisseur> v; v.push_back (cFournisseur("square Georges Brassens"));
Dans l'ordre :
création de l'objet temporaire (constructeur cFournisseur(char const*) ). création de l'objet qui se trouve dans le vector<> (constructeur de copie : cFournisseur(cFournisseur const&) ). destruction du temporaire (destructeur ~cFournisseur() ).
-- ;-)
On Wed, 11 Aug 2004 22:42:47 +0200, David MAREC
<dmarec.spam@spambox.invalid>:
Si je comprend bien, l'objet temporaire va bel et bien être détruit par tous
les mécanismes idoines (~objet()) et la copie sera aussi créée en
appliquant les mécanismes associés (objet()) ?
Simplifions un peu le code :
std::vector<cFournisseur> v;
v.push_back (cFournisseur("square Georges Brassens"));
Dans l'ordre :
création de l'objet temporaire
(constructeur cFournisseur(char const*) ).
création de l'objet qui se trouve dans le vector<>
(constructeur de copie : cFournisseur(cFournisseur const&) ).
destruction du temporaire
(destructeur ~cFournisseur() ).
Si je comprend bien, l'objet temporaire va bel et bien être détruit par tous les mécanismes idoines (~objet()) et la copie sera aussi créée en appliquant les mécanismes associés (objet()) ?
Simplifions un peu le code :
std::vector<cFournisseur> v; v.push_back (cFournisseur("square Georges Brassens"));
Dans l'ordre :
création de l'objet temporaire (constructeur cFournisseur(char const*) ). création de l'objet qui se trouve dans le vector<> (constructeur de copie : cFournisseur(cFournisseur const&) ). destruction du temporaire (destructeur ~cFournisseur() ).