Je compile (g++ 3.4.2), j'exécute et j'obtiens un comportement étrange,
notifié par Valgrind ("Invalid free() / delete...") :
vincent@sherlock:~/tmp$ valgrind ./op
==10368== Memcheck, a memory error detector for x86-linux.
==10368== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
==10368== Using valgrind-2.2.0, a program supervision framework for
x86-linux.
==10368== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
==10368== For more details, rerun with: -v
==10368==
==10368== Invalid free() / delete / delete[]
==10368== at 0x1B905616: operator delete(void*) (vg_replace_malloc.c:156)
==10368== by 0x8048698: B::~B() (op.cpp:18)
==10368== by 0x804866D: main (op.cpp:30)
==10368== Address 0x1BB5C060 is 0 bytes inside a block of size 4 free'd
==10368== at 0x1B905616: operator delete(void*) (vg_replace_malloc.c:156)
==10368== by 0x8048698: B::~B() (op.cpp:18)
==10368== by 0x8048639: main (op.cpp:30)
==10368==
==10368== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 17 from 1)
==10368== malloc/free: in use at exit: 4 bytes in 1 blocks.
==10368== malloc/free: 2 allocs, 2 frees, 8 bytes allocated.
==10368== For a detailed leak analysis, rerun with: --leak-check=yes
==10368== For counts of detected errors, rerun with: -v
Bizarrement, lorsque j'enlève la ligne "b1 = b2", tout se passe normalement
(pas de fuite mémoire, pas de problème de delete(), etc.). Dans les deux
cas, l'exécution ne provoque aucune erreur (mis à part le message de
Valgrind dans le premier cas).
J'ai un peu de mal à comprendre ce qu'il se passe, ce code étant pourtant
parfaitement valide, peut-être que quelqu'un ici pourra m'éclairer...
Je soupçonne un bug de Valgrind mais je voudrais être sûr.
Merci d'avance pour vos réponses.
Vincent
--
vmime, une bibliothèque C++ sous licence GPL pour parser et générer
des messages au format MIME : http://www.sourceforge.net/projects/vmime/
struct B : public A { B() { p = new int; } ~B() { delete (p); }
void f() { }
int* p; };
int main() { B b1; B b2;
b1 = b2; } =============================================== > Je compile (g++ 3.4.2), j'exécute et j'obtiens un comportement étrange, notifié par Valgrind ("Invalid free() / delete...") :
Tu as deux B partageant un lien vers la zone allouée dynamiquement. Il y a donc deux destructeurs qui essaieront de la libérer, d'où l'erreur. Il faut apprendre à faire les constructeur de copie et operator= nécessaires.
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Dans le message 4175898c$0$30856$636a15ce@news.free.fr,
struct B : public A
{
B() { p = new int; }
~B() { delete (p); }
void f() { }
int* p;
};
int main()
{
B b1;
B b2;
b1 = b2;
}
=============================================== >
Je compile (g++ 3.4.2), j'exécute et j'obtiens un comportement
étrange, notifié par Valgrind ("Invalid free() / delete...") :
Tu as deux B partageant un lien vers la zone allouée dynamiquement.
Il y a donc deux destructeurs qui essaieront de la libérer, d'où
l'erreur. Il faut apprendre à faire les constructeur de copie et
operator= nécessaires.
--
Michel Michaud mm@gdzid.com
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
struct B : public A { B() { p = new int; } ~B() { delete (p); }
void f() { }
int* p; };
int main() { B b1; B b2;
b1 = b2; } =============================================== > Je compile (g++ 3.4.2), j'exécute et j'obtiens un comportement étrange, notifié par Valgrind ("Invalid free() / delete...") :
Tu as deux B partageant un lien vers la zone allouée dynamiquement. Il y a donc deux destructeurs qui essaieront de la libérer, d'où l'erreur. Il faut apprendre à faire les constructeur de copie et operator= nécessaires.
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Vincent Richard
Tu as deux B partageant un lien vers la zone allouée dynamiquement. Il y a donc deux destructeurs qui essaieront de la libérer, d'où l'erreur. Il faut apprendre à faire les constructeur de copie et operator= nécessaires.
Aïe, c'était tout bête, et crois que je viens de comprendre mon erreur.
En fait, dans le code d'origine, f() est en fait copyFrom() qui se charge de copier l'objet. Ce copyFrom() est donc appelée par operator=() de la classe de base :
struct A { virtual ~A() { }
A& operator=(const A& a) { copyFrom(a); return (*this); }
virtual void copyFrom(const A& a) = 0; };
struct B : public A { void B::copyFrom(const A& a) { const B& b = dynamic_cast <const B&>(a);
*p = *(b.p) } };
Il ne m'a pas semblé nécessaire de le mettre dans mon code de test car dans tous les cas, l'erreur se produisait (du fait du B::operator implicite indiqué plus loin).
Il semblerait que quand on fait :
b1 = b2;
ce n'est pas A::operator=() qui est appelée (pas en premier), mais B::operator=(), qui est créée implicitement par le compilateur (et qui ne fait qu'une "bête" copie de pointeur).
En effet, ça fonctionne correctement en ajoutant :
B& B::operator=(const B& b) { A::operator=(b); return (*this); }
Il est donc obligatoire d'implanter operator=() dans toutes les classes (et pas seulement sur A) ? (même si c'est juste un appel à A::operator=)
Est-ce exact ?
Merci.
Vincent
-- vmime, une bibliothèque C++ sous licence GPL pour parser et générer des messages au format MIME : http://www.sourceforge.net/projects/vmime/
Tu as deux B partageant un lien vers la zone allouée dynamiquement.
Il y a donc deux destructeurs qui essaieront de la libérer, d'où
l'erreur. Il faut apprendre à faire les constructeur de copie et
operator= nécessaires.
Aïe, c'était tout bête, et crois que je viens de comprendre mon erreur.
En fait, dans le code d'origine, f() est en fait copyFrom() qui se
charge de copier l'objet. Ce copyFrom() est donc appelée par
operator=() de la classe de base :
struct A
{
virtual ~A() { }
A& operator=(const A& a)
{
copyFrom(a);
return (*this);
}
virtual void copyFrom(const A& a) = 0;
};
struct B : public A
{
void B::copyFrom(const A& a)
{
const B& b = dynamic_cast <const B&>(a);
*p = *(b.p)
}
};
Il ne m'a pas semblé nécessaire de le mettre dans mon code de test
car dans tous les cas, l'erreur se produisait (du fait du B::operator implicite indiqué plus loin).
Il semblerait que quand on fait :
b1 = b2;
ce n'est pas A::operator=() qui est appelée (pas en premier), mais
B::operator=(), qui est créée implicitement par le compilateur (et qui ne
fait qu'une "bête" copie de pointeur).
En effet, ça fonctionne correctement en ajoutant :
B& B::operator=(const B& b)
{
A::operator=(b);
return (*this);
}
Il est donc obligatoire d'implanter operator=() dans toutes les
classes (et pas seulement sur A) ? (même si c'est juste un appel
à A::operator=)
Est-ce exact ?
Merci.
Vincent
--
vmime, une bibliothèque C++ sous licence GPL pour parser et générer
des messages au format MIME : http://www.sourceforge.net/projects/vmime/
Tu as deux B partageant un lien vers la zone allouée dynamiquement. Il y a donc deux destructeurs qui essaieront de la libérer, d'où l'erreur. Il faut apprendre à faire les constructeur de copie et operator= nécessaires.
Aïe, c'était tout bête, et crois que je viens de comprendre mon erreur.
En fait, dans le code d'origine, f() est en fait copyFrom() qui se charge de copier l'objet. Ce copyFrom() est donc appelée par operator=() de la classe de base :
struct A { virtual ~A() { }
A& operator=(const A& a) { copyFrom(a); return (*this); }
virtual void copyFrom(const A& a) = 0; };
struct B : public A { void B::copyFrom(const A& a) { const B& b = dynamic_cast <const B&>(a);
*p = *(b.p) } };
Il ne m'a pas semblé nécessaire de le mettre dans mon code de test car dans tous les cas, l'erreur se produisait (du fait du B::operator implicite indiqué plus loin).
Il semblerait que quand on fait :
b1 = b2;
ce n'est pas A::operator=() qui est appelée (pas en premier), mais B::operator=(), qui est créée implicitement par le compilateur (et qui ne fait qu'une "bête" copie de pointeur).
En effet, ça fonctionne correctement en ajoutant :
B& B::operator=(const B& b) { A::operator=(b); return (*this); }
Il est donc obligatoire d'implanter operator=() dans toutes les classes (et pas seulement sur A) ? (même si c'est juste un appel à A::operator=)
Est-ce exact ?
Merci.
Vincent
-- vmime, une bibliothèque C++ sous licence GPL pour parser et générer des messages au format MIME : http://www.sourceforge.net/projects/vmime/
kanze
Vincent Richard wrote in message news:<4175898c$0$30856$...
Voici un extrait de code très simple (et totalement inutile) :
=============================================== > struct A { virtual ~A() { }
A& operator=(const A& a) { f(); return (*this); }
virtual void f() = 0; };
struct B : public A { B() { p = new int; } ~B() { delete (p); }
void f() { }
int* p; };
int main() { B b1; B b2;
b1 = b2; } =============================================== Je compile (g++ 3.4.2), j'exécute et j'obtiens un comportement étrange, notifié par Valgrind ("Invalid free() / delete...") :
:~/tmp$ valgrind ./op =368== Memcheck, a memory error detector for x86-linux. =368== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al. =368== Using valgrind-2.2.0, a program supervision framework for x86-linux. =368== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al. =368== For more details, rerun with: -v =368== =368== Invalid free() / delete / delete[] =368== at 0x1B905616: operator delete(void*) (vg_replace_malloc.c:156) =368== by 0x8048698: B::~B() (op.cpp:18) =368== by 0x804866D: main (op.cpp:30) =368== Address 0x1BB5C060 is 0 bytes inside a block of size 4 free'd =368== at 0x1B905616: operator delete(void*) (vg_replace_malloc.c:156) =368== by 0x8048698: B::~B() (op.cpp:18) =368== by 0x8048639: main (op.cpp:30) =368== =368== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 17 from 1) =368== malloc/free: in use at exit: 4 bytes in 1 blocks. =368== malloc/free: 2 allocs, 2 frees, 8 bytes allocated. =368== For a detailed leak analysis, rerun with: --leak-check=yes =368== For counts of detected errors, rerun with: -v
Bizarrement, lorsque j'enlève la ligne "b1 = b2", tout se passe normalement (pas de fuite mémoire, pas de problème de delete(), etc.). Dans les deux cas, l'exécution ne provoque aucune erreur (mis à part le message de Valgrind dans le premier cas).
Normal. Tu as negligé la règle des quatre : s'il te faut un des quatre suivants : constructeur de copie, constructeur de défaut, opérateur d'affectation, destructeur ; il t'en faut tous les quatre. (Il y a une exception quand la raison pour le destructeur est de le rendre virtuel, ou qu'on a fourni un des quatre seulement afin qu'il ne soit pas public.)
Lire Scott Meyers.
J'ai un peu de mal à comprendre ce qu'il se passe, ce code étant pourtant parfaitement valide, peut-être que quelqu'un ici pourra m'éclairer...
Je soupçonne un bug de Valgrind mais je voudrais être sûr.
C'est un peu effronté de ta part, non ? Manifestement, tu n'as jamais encore écrit un programme en C++, et cependant, du coup « ce code étant pourtant parfaitement valide » (il ne l'est pas, et la règle qu'il viole est un des plus fondamentale) et un boggue dans Valgrind.
-- James Kanze GABI Software http://www.gabi-soft.fr 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
Vincent Richard <chere-loque.MARRE-DE-LA-PUB@wanadoo.fr.invalid> wrote
in message news:<4175898c$0$30856$636a15ce@news.free.fr>...
Voici un extrait de code très simple (et totalement inutile) :
=============================================== > struct A
{
virtual ~A() { }
A& operator=(const A& a)
{
f();
return (*this);
}
virtual void f() = 0;
};
struct B : public A
{
B() { p = new int; }
~B() { delete (p); }
void f() { }
int* p;
};
int main()
{
B b1;
B b2;
b1 = b2;
}
===============================================
Je compile (g++ 3.4.2), j'exécute et j'obtiens un comportement
étrange, notifié par Valgrind ("Invalid free() / delete...") :
vincent@sherlock:~/tmp$ valgrind ./op
=368== Memcheck, a memory error detector for x86-linux.
=368== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.
=368== Using valgrind-2.2.0, a program supervision framework for
x86-linux.
=368== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.
=368== For more details, rerun with: -v
=368==
=368== Invalid free() / delete / delete[]
=368== at 0x1B905616: operator delete(void*) (vg_replace_malloc.c:156)
=368== by 0x8048698: B::~B() (op.cpp:18)
=368== by 0x804866D: main (op.cpp:30)
=368== Address 0x1BB5C060 is 0 bytes inside a block of size 4 free'd
=368== at 0x1B905616: operator delete(void*) (vg_replace_malloc.c:156)
=368== by 0x8048698: B::~B() (op.cpp:18)
=368== by 0x8048639: main (op.cpp:30)
=368==
=368== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 17 from 1)
=368== malloc/free: in use at exit: 4 bytes in 1 blocks.
=368== malloc/free: 2 allocs, 2 frees, 8 bytes allocated.
=368== For a detailed leak analysis, rerun with: --leak-check=yes
=368== For counts of detected errors, rerun with: -v
Bizarrement, lorsque j'enlève la ligne "b1 = b2", tout se passe
normalement (pas de fuite mémoire, pas de problème de delete(), etc.).
Dans les deux cas, l'exécution ne provoque aucune erreur (mis à part
le message de Valgrind dans le premier cas).
Normal. Tu as negligé la règle des quatre : s'il te faut un des quatre
suivants : constructeur de copie, constructeur de défaut, opérateur
d'affectation, destructeur ; il t'en faut tous les quatre. (Il y a une
exception quand la raison pour le destructeur est de le rendre virtuel,
ou qu'on a fourni un des quatre seulement afin qu'il ne soit pas
public.)
Lire Scott Meyers.
J'ai un peu de mal à comprendre ce qu'il se passe, ce code étant
pourtant parfaitement valide, peut-être que quelqu'un ici pourra
m'éclairer...
Je soupçonne un bug de Valgrind mais je voudrais être sûr.
C'est un peu effronté de ta part, non ? Manifestement, tu n'as jamais
encore écrit un programme en C++, et cependant, du coup « ce code étant
pourtant parfaitement valide » (il ne l'est pas, et la règle qu'il viole
est un des plus fondamentale) et un boggue dans Valgrind.
--
James Kanze GABI Software http://www.gabi-soft.fr
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
Vincent Richard wrote in message news:<4175898c$0$30856$...
Voici un extrait de code très simple (et totalement inutile) :
=============================================== > struct A { virtual ~A() { }
A& operator=(const A& a) { f(); return (*this); }
virtual void f() = 0; };
struct B : public A { B() { p = new int; } ~B() { delete (p); }
void f() { }
int* p; };
int main() { B b1; B b2;
b1 = b2; } =============================================== Je compile (g++ 3.4.2), j'exécute et j'obtiens un comportement étrange, notifié par Valgrind ("Invalid free() / delete...") :
:~/tmp$ valgrind ./op =368== Memcheck, a memory error detector for x86-linux. =368== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al. =368== Using valgrind-2.2.0, a program supervision framework for x86-linux. =368== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al. =368== For more details, rerun with: -v =368== =368== Invalid free() / delete / delete[] =368== at 0x1B905616: operator delete(void*) (vg_replace_malloc.c:156) =368== by 0x8048698: B::~B() (op.cpp:18) =368== by 0x804866D: main (op.cpp:30) =368== Address 0x1BB5C060 is 0 bytes inside a block of size 4 free'd =368== at 0x1B905616: operator delete(void*) (vg_replace_malloc.c:156) =368== by 0x8048698: B::~B() (op.cpp:18) =368== by 0x8048639: main (op.cpp:30) =368== =368== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 17 from 1) =368== malloc/free: in use at exit: 4 bytes in 1 blocks. =368== malloc/free: 2 allocs, 2 frees, 8 bytes allocated. =368== For a detailed leak analysis, rerun with: --leak-check=yes =368== For counts of detected errors, rerun with: -v
Bizarrement, lorsque j'enlève la ligne "b1 = b2", tout se passe normalement (pas de fuite mémoire, pas de problème de delete(), etc.). Dans les deux cas, l'exécution ne provoque aucune erreur (mis à part le message de Valgrind dans le premier cas).
Normal. Tu as negligé la règle des quatre : s'il te faut un des quatre suivants : constructeur de copie, constructeur de défaut, opérateur d'affectation, destructeur ; il t'en faut tous les quatre. (Il y a une exception quand la raison pour le destructeur est de le rendre virtuel, ou qu'on a fourni un des quatre seulement afin qu'il ne soit pas public.)
Lire Scott Meyers.
J'ai un peu de mal à comprendre ce qu'il se passe, ce code étant pourtant parfaitement valide, peut-être que quelqu'un ici pourra m'éclairer...
Je soupçonne un bug de Valgrind mais je voudrais être sûr.
C'est un peu effronté de ta part, non ? Manifestement, tu n'as jamais encore écrit un programme en C++, et cependant, du coup « ce code étant pourtant parfaitement valide » (il ne l'est pas, et la règle qu'il viole est un des plus fondamentale) et un boggue dans Valgrind.
-- James Kanze GABI Software http://www.gabi-soft.fr 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
Vincent Richard
Normal. Tu as negligé la règle des quatre : s'il te faut un des quatre suivants : constructeur de copie, constructeur de défaut, opérateur d'affectation, destructeur ; il t'en faut tous les quatre. (Il y a une exception quand la raison pour le destructeur est de le rendre virtuel, ou qu'on a fourni un des quatre seulement afin qu'il ne soit pas public.)
Lire Scott Meyers.
Merci du conseil.
Mais pourquoi donc ce n'est pas l'operator=() de la classe de base qui est appelé quand il n'est pas défini dans une classe ? Y'a-t-il une raison à cela ?
En clair, je cherchais à n'écrire operator=() qu'une seule fois (un peu par feignantise, je l'avoue :-)), et à implanter, par contre, un copyFrom() dans toutes les classes.
Je soupçonne un bug de Valgrind mais je voudrais être sûr.
C'est un peu effronté de ta part, non ?
En effet, je me suis un peu emporté et j'en suis désolé (d'autant plus que Valgrind m'a déjà plusieurs fois permis de me trouver de grosses erreurs). Peut-être faudrait-il que je travaille un peu moins tard le soir...
Manifestement, tu n'as jamais encore écrit un programme en C++, et cependant, du coup « ce code étant pourtant parfaitement valide » (il ne l'est pas, et la règle qu'il viole est un des plus fondamentale) et un boggue dans Valgrind.
Je ne prétend nullement être un expert, et d'ailleurs c'est comme tout, il faut bien apprendre un jour (même si ça fait un moment que je m'y suis mis).
Pour le "parfaitement" valide, je m'appuyais en fait sur le fait que mon compilateur (g++) ne sortait aucun warning (même avec les flags -W -Wall -ansi -pedantic). Maintenant, tout le monde n'a pas la norme C++ comme livre de chevet...
Ce n'était tout de même pas la peine de prendre un ton si méprisable.
Bonne journée.
Vincent
-- vmime, une bibliothèque C++ sous licence GPL pour parser et générer des messages au format MIME : http://www.sourceforge.net/projects/vmime/
Normal. Tu as negligé la règle des quatre : s'il te faut un des quatre
suivants : constructeur de copie, constructeur de défaut, opérateur
d'affectation, destructeur ; il t'en faut tous les quatre. (Il y a une
exception quand la raison pour le destructeur est de le rendre virtuel,
ou qu'on a fourni un des quatre seulement afin qu'il ne soit pas
public.)
Lire Scott Meyers.
Merci du conseil.
Mais pourquoi donc ce n'est pas l'operator=() de la classe de base qui est
appelé quand il n'est pas défini dans une classe ? Y'a-t-il une raison à
cela ?
En clair, je cherchais à n'écrire operator=() qu'une seule fois (un peu
par feignantise, je l'avoue :-)), et à implanter, par contre, un copyFrom()
dans toutes les classes.
Je soupçonne un bug de Valgrind mais je voudrais être sûr.
C'est un peu effronté de ta part, non ?
En effet, je me suis un peu emporté et j'en suis désolé (d'autant plus que
Valgrind m'a déjà plusieurs fois permis de me trouver de grosses erreurs).
Peut-être faudrait-il que je travaille un peu moins tard le soir...
Manifestement, tu n'as jamais encore écrit un programme en C++, et
cependant, du coup « ce code étant pourtant parfaitement valide » (il ne
l'est pas, et la règle qu'il viole est un des plus fondamentale) et un
boggue dans Valgrind.
Je ne prétend nullement être un expert, et d'ailleurs c'est comme tout,
il faut bien apprendre un jour (même si ça fait un moment que je m'y
suis mis).
Pour le "parfaitement" valide, je m'appuyais en fait sur le fait que mon
compilateur (g++) ne sortait aucun warning (même avec les flags -W -Wall
-ansi -pedantic). Maintenant, tout le monde n'a pas la norme C++ comme
livre de chevet...
Ce n'était tout de même pas la peine de prendre un ton si méprisable.
Bonne journée.
Vincent
--
vmime, une bibliothèque C++ sous licence GPL pour parser et générer
des messages au format MIME : http://www.sourceforge.net/projects/vmime/
Normal. Tu as negligé la règle des quatre : s'il te faut un des quatre suivants : constructeur de copie, constructeur de défaut, opérateur d'affectation, destructeur ; il t'en faut tous les quatre. (Il y a une exception quand la raison pour le destructeur est de le rendre virtuel, ou qu'on a fourni un des quatre seulement afin qu'il ne soit pas public.)
Lire Scott Meyers.
Merci du conseil.
Mais pourquoi donc ce n'est pas l'operator=() de la classe de base qui est appelé quand il n'est pas défini dans une classe ? Y'a-t-il une raison à cela ?
En clair, je cherchais à n'écrire operator=() qu'une seule fois (un peu par feignantise, je l'avoue :-)), et à implanter, par contre, un copyFrom() dans toutes les classes.
Je soupçonne un bug de Valgrind mais je voudrais être sûr.
C'est un peu effronté de ta part, non ?
En effet, je me suis un peu emporté et j'en suis désolé (d'autant plus que Valgrind m'a déjà plusieurs fois permis de me trouver de grosses erreurs). Peut-être faudrait-il que je travaille un peu moins tard le soir...
Manifestement, tu n'as jamais encore écrit un programme en C++, et cependant, du coup « ce code étant pourtant parfaitement valide » (il ne l'est pas, et la règle qu'il viole est un des plus fondamentale) et un boggue dans Valgrind.
Je ne prétend nullement être un expert, et d'ailleurs c'est comme tout, il faut bien apprendre un jour (même si ça fait un moment que je m'y suis mis).
Pour le "parfaitement" valide, je m'appuyais en fait sur le fait que mon compilateur (g++) ne sortait aucun warning (même avec les flags -W -Wall -ansi -pedantic). Maintenant, tout le monde n'a pas la norme C++ comme livre de chevet...
Ce n'était tout de même pas la peine de prendre un ton si méprisable.
Bonne journée.
Vincent
-- vmime, une bibliothèque C++ sous licence GPL pour parser et générer des messages au format MIME : http://www.sourceforge.net/projects/vmime/
James Kanze
Vincent Richard writes:
|> Mais pourquoi donc ce n'est pas l'operator=() de la classe de base |> qui est appelé quand il n'est pas défini dans une classe ?
Il est appelé. Quand tu ne définis pas d'opérateur d'affectation, le compilateur en génère un, qui appelle les opérateurs d'affectation pour toutes les classes de base et pour toutes les membres.
|> Y'a-t-il une raison à cela ?
|> En clair, je cherchais à n'écrire operator=() qu'une seule fois (un |> peu par feignantise, je l'avoue :-)), et à implanter, par contre, un |> copyFrom() dans toutes les classes.
Et qu'est ce que ça change ?
(En fait, c'est assez rare qu'une classe polymorphique supporte l'affectation. L'héritage et l'affectation ne vont pas bien ensemble.)
-- James Kanze 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
Vincent Richard <chere-loque.MARRE-DE-LA-PUB@wanadoo.fr.invalid> writes:
|> Mais pourquoi donc ce n'est pas l'operator=() de la classe de base
|> qui est appelé quand il n'est pas défini dans une classe ?
Il est appelé. Quand tu ne définis pas d'opérateur d'affectation, le
compilateur en génère un, qui appelle les opérateurs d'affectation pour
toutes les classes de base et pour toutes les membres.
|> Y'a-t-il une raison à cela ?
|> En clair, je cherchais à n'écrire operator=() qu'une seule fois (un
|> peu par feignantise, je l'avoue :-)), et à implanter, par contre, un
|> copyFrom() dans toutes les classes.
Et qu'est ce que ça change ?
(En fait, c'est assez rare qu'une classe polymorphique supporte
l'affectation. L'héritage et l'affectation ne vont pas bien ensemble.)
--
James Kanze
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
|> Mais pourquoi donc ce n'est pas l'operator=() de la classe de base |> qui est appelé quand il n'est pas défini dans une classe ?
Il est appelé. Quand tu ne définis pas d'opérateur d'affectation, le compilateur en génère un, qui appelle les opérateurs d'affectation pour toutes les classes de base et pour toutes les membres.
|> Y'a-t-il une raison à cela ?
|> En clair, je cherchais à n'écrire operator=() qu'une seule fois (un |> peu par feignantise, je l'avoue :-)), et à implanter, par contre, un |> copyFrom() dans toutes les classes.
Et qu'est ce que ça change ?
(En fait, c'est assez rare qu'une classe polymorphique supporte l'affectation. L'héritage et l'affectation ne vont pas bien ensemble.)
-- James Kanze 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
Andre Heinen
On 20 Oct 2004 20:47:58 +0200, James Kanze wrote:
(En fait, c'est assez rare qu'une classe polymorphique supporte l'affectation. L'héritage et l'affectation ne vont pas bien ensemble.)
Quand on fait une classe polymorphique, vaut-il mieux interdire l'affectation, ou mettre un opérateur d'affectation en espérant que l'utilisateur ne mélangera pas les types?
-- Andre Heinen My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
On 20 Oct 2004 20:47:58 +0200, James Kanze <james.kanze@free.fr>
wrote:
(En fait, c'est assez rare qu'une classe polymorphique supporte
l'affectation. L'héritage et l'affectation ne vont pas bien ensemble.)
Quand on fait une classe polymorphique, vaut-il mieux interdire
l'affectation, ou mettre un opérateur d'affectation en espérant
que l'utilisateur ne mélangera pas les types?
--
Andre Heinen
My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
(En fait, c'est assez rare qu'une classe polymorphique supporte l'affectation. L'héritage et l'affectation ne vont pas bien ensemble.)
Quand on fait une classe polymorphique, vaut-il mieux interdire l'affectation, ou mettre un opérateur d'affectation en espérant que l'utilisateur ne mélangera pas les types?
-- Andre Heinen My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
Falk Tannhäuser
Andre Heinen wrote:
On 20 Oct 2004 20:47:58 +0200, James Kanze wrote:
(En fait, c'est assez rare qu'une classe polymorphique supporte l'affectation. L'héritage et l'affectation ne vont pas bien ensemble. )
Quand on fait une classe polymorphique, vaut-il mieux interdire l'affectation, ou mettre un opérateur d'affectation en espérant que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-) Si on n'as pas besoin de l'affectation (ce qui est très souvent le cas pour les classes censées représenter des entités du "monde réel" au sens large) on l'interdit pour être peinard. Si on en a besoin, on peut se tourner vers une solution du genre "lettre - enveloppe", permettant de simuler un changement du type dynamique de l'objet affecté (chose que le C++ ne supporte pas directement). Une affectation d'enveloppes est alors implémentée par un appel à la fonction virtuelle 'lettre* clone(lettre const&)'.
Falk
Andre Heinen wrote:
On 20 Oct 2004 20:47:58 +0200, James Kanze <james.kanze@free.fr>
wrote:
(En fait, c'est assez rare qu'une classe polymorphique supporte
l'affectation. L'héritage et l'affectation ne vont pas bien ensemble. )
Quand on fait une classe polymorphique, vaut-il mieux interdire
l'affectation, ou mettre un opérateur d'affectation en espérant
que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-)
Si on n'as pas besoin de l'affectation (ce qui est très souvent le cas
pour les classes censées représenter des entités du "monde réel" au sens
large) on l'interdit pour être peinard.
Si on en a besoin, on peut se tourner vers une solution du genre
"lettre - enveloppe", permettant de simuler un changement du type
dynamique de l'objet affecté (chose que le C++ ne supporte pas
directement). Une affectation d'enveloppes est alors implémentée
par un appel à la fonction virtuelle 'lettre* clone(lettre const&)'.
(En fait, c'est assez rare qu'une classe polymorphique supporte l'affectation. L'héritage et l'affectation ne vont pas bien ensemble. )
Quand on fait une classe polymorphique, vaut-il mieux interdire l'affectation, ou mettre un opérateur d'affectation en espérant que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-) Si on n'as pas besoin de l'affectation (ce qui est très souvent le cas pour les classes censées représenter des entités du "monde réel" au sens large) on l'interdit pour être peinard. Si on en a besoin, on peut se tourner vers une solution du genre "lettre - enveloppe", permettant de simuler un changement du type dynamique de l'objet affecté (chose que le C++ ne supporte pas directement). Une affectation d'enveloppes est alors implémentée par un appel à la fonction virtuelle 'lettre* clone(lettre const&)'.
Falk
Falk Tannhäuser
Andre Heinen wrote:
On 20 Oct 2004 20:47:58 +0200, James Kanze wrote:
(En fait, c'est assez rare qu'une classe polymorphique supporte l'affectation. L'héritage et l'affectation ne vont pas bien ensemble. )
Quand on fait une classe polymorphique, vaut-il mieux interdire l'affectation, ou mettre un opérateur d'affectation en espérant que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-)
Si on n'a pas besoin de l'affectation (ce qui est très souvent le cas pour les classes censées représenter des entités du "monde réel" au sens large) on l'interdit pour être peinard. Si on en a besoin, on peut se tourner vers une solution du genre "lettre - enveloppe", permettant de simuler un changement du type dynamique de l'objet affecté (chose que le C++ ne supporte pas directement). Une affectation d'enveloppes est alors implémentée par un appel à la fonction virtuelle 'lettre* lettre::clone() const'.
Falk
Andre Heinen wrote:
On 20 Oct 2004 20:47:58 +0200, James Kanze <james.kanze@free.fr>
wrote:
(En fait, c'est assez rare qu'une classe polymorphique supporte
l'affectation. L'héritage et l'affectation ne vont pas bien ensemble. )
Quand on fait une classe polymorphique, vaut-il mieux interdire
l'affectation, ou mettre un opérateur d'affectation en espérant
que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-)
Si on n'a pas besoin de l'affectation (ce qui est très souvent le cas
pour les classes censées représenter des entités du "monde réel" au sens
large) on l'interdit pour être peinard.
Si on en a besoin, on peut se tourner vers une solution du genre
"lettre - enveloppe", permettant de simuler un changement du type
dynamique de l'objet affecté (chose que le C++ ne supporte pas
directement). Une affectation d'enveloppes est alors implémentée
par un appel à la fonction virtuelle 'lettre* lettre::clone() const'.
(En fait, c'est assez rare qu'une classe polymorphique supporte l'affectation. L'héritage et l'affectation ne vont pas bien ensemble. )
Quand on fait une classe polymorphique, vaut-il mieux interdire l'affectation, ou mettre un opérateur d'affectation en espérant que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-)
Si on n'a pas besoin de l'affectation (ce qui est très souvent le cas pour les classes censées représenter des entités du "monde réel" au sens large) on l'interdit pour être peinard. Si on en a besoin, on peut se tourner vers une solution du genre "lettre - enveloppe", permettant de simuler un changement du type dynamique de l'objet affecté (chose que le C++ ne supporte pas directement). Une affectation d'enveloppes est alors implémentée par un appel à la fonction virtuelle 'lettre* lettre::clone() const'.
Falk
Andre Heinen
On Thu, 21 Oct 2004 14:26:55 +0200, Falk Tannhäuser wrote:
Andre Heinen wrote:
Quand on fait une classe polymorphique, vaut-il mieux interdire l'affectation, ou mettre un opérateur d'affectation en espérant que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-)
Je me rends compte, en me relisant, que le simple choix des mots de ma question donnait déjà la réponse... :-)
-- Andre Heinen My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
On Thu, 21 Oct 2004 14:26:55 +0200, Falk Tannhäuser
<falk.tannhauser@crf.canon.fr> wrote:
Andre Heinen wrote:
Quand on fait une classe polymorphique, vaut-il mieux interdire
l'affectation, ou mettre un opérateur d'affectation en espérant
que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-)
Je me rends compte, en me relisant, que le simple choix des mots
de ma question donnait déjà la réponse... :-)
--
Andre Heinen
My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
On Thu, 21 Oct 2004 14:26:55 +0200, Falk Tannhäuser wrote:
Andre Heinen wrote:
Quand on fait une classe polymorphique, vaut-il mieux interdire l'affectation, ou mettre un opérateur d'affectation en espérant que l'utilisateur ne mélangera pas les types?
Mieux vaut pas trop espérer de l'utilisateur :-)
Je me rends compte, en me relisant, que le simple choix des mots de ma question donnait déjà la réponse... :-)
-- Andre Heinen My address, rot13-encoded: n qbg urvara ng rhebcrnayvax qbg pbz
James Kanze
Falk Tannhäuser writes:
|> Andre Heinen wrote:
|> > On 20 Oct 2004 20:47:58 +0200, James Kanze |> > wrote:
|> >>(En fait, c'est assez rare qu'une classe polymorphique supporte |> >>l'affectation. L'héritage et l'affectation ne vont pas bien |> >>ensemble.) |> > Quand on fait une classe polymorphique, vaut-il |> >>mieux interdire |> > l'affectation, ou mettre un opérateur |> >>d'affectation en espérant |> > que l'utilisateur ne mélangera pas |> >>les types?
|> Mieux vaut pas trop espérer de l'utilisateur :-)
On dirait que tu as de l'expérience pratique:-).
-- James Kanze 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
|> > On 20 Oct 2004 20:47:58 +0200, James Kanze <james.kanze@free.fr>
|> > wrote:
|> >>(En fait, c'est assez rare qu'une classe polymorphique supporte
|> >>l'affectation. L'héritage et l'affectation ne vont pas bien
|> >>ensemble.) |> > Quand on fait une classe polymorphique, vaut-il
|> >>mieux interdire |> > l'affectation, ou mettre un opérateur
|> >>d'affectation en espérant |> > que l'utilisateur ne mélangera pas
|> >>les types?
|> Mieux vaut pas trop espérer de l'utilisateur :-)
On dirait que tu as de l'expérience pratique:-).
--
James Kanze
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
|> > On 20 Oct 2004 20:47:58 +0200, James Kanze |> > wrote:
|> >>(En fait, c'est assez rare qu'une classe polymorphique supporte |> >>l'affectation. L'héritage et l'affectation ne vont pas bien |> >>ensemble.) |> > Quand on fait une classe polymorphique, vaut-il |> >>mieux interdire |> > l'affectation, ou mettre un opérateur |> >>d'affectation en espérant |> > que l'utilisateur ne mélangera pas |> >>les types?
|> Mieux vaut pas trop espérer de l'utilisateur :-)
On dirait que tu as de l'expérience pratique:-).
-- James Kanze 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