Voici un problème qui m'ennuie à cause de l'héritage et du polymorphisme.
J'ai créé la classe abstraite Object avec les méthodes init et destroy
comme étant virtuelle pure.
Je crée la class NewObject à partir d'Object et j'implémente donc init et destroy
afin de pouvoir instancier un objet de la classe NewObject.
normalement, "this" représente l'objet dynamique, donc, normalement this->init () se trouvant
dans Object devrait faire appel à NewObject::init et non à Object::init.
Ici on est en train de construire Object NewObject n'est pas encore initialisé Ca n'a pas de sens d'appeler une fonction de NewObject (init).
J'imagine que le contexte est plus complexe, mais pourquoi ne pas mettre le code d'init dans le constructeur de NewObject et celui de destroy dans son destructeur ?
Ici on est en train de construire Object
NewObject n'est pas encore initialisé
Ca n'a pas de sens d'appeler une fonction de NewObject (init).
J'imagine que le contexte est plus complexe, mais pourquoi ne pas mettre le
code d'init dans le constructeur de NewObject et celui de destroy dans son
destructeur ?
Ici on est en train de construire Object NewObject n'est pas encore initialisé Ca n'a pas de sens d'appeler une fonction de NewObject (init).
J'imagine que le contexte est plus complexe, mais pourquoi ne pas mettre le code d'init dans le constructeur de NewObject et celui de destroy dans son destructeur ?
Ici on est en train de construire Object NewObject n'est pas encore initialisé Ca n'a pas de sens d'appeler une fonction de NewObject (init).
J'imagine que le contexte est plus complexe, mais pourquoi ne pas mettre le code d'init dans le constructeur de NewObject et celui de destroy dans son destructeur ?
Parce que j'essaie de surcharger new, new[], delete, delete[] via un malloc & free, afin d'essayer de créer un memory manager et qu'à ce moment là, le new n'appellera plus le constructeur de la classe que j'instancie.
Ici on est en train de construire Object
NewObject n'est pas encore initialisé
Ca n'a pas de sens d'appeler une fonction de NewObject (init).
J'imagine que le contexte est plus complexe, mais pourquoi ne pas mettre le
code d'init dans le constructeur de NewObject et celui de destroy dans son
destructeur ?
Parce que j'essaie de surcharger new, new[], delete, delete[] via un malloc & free, afin d'essayer de créer un memory manager
et qu'à ce moment là, le new n'appellera plus le constructeur de la classe que j'instancie.
Ici on est en train de construire Object NewObject n'est pas encore initialisé Ca n'a pas de sens d'appeler une fonction de NewObject (init).
J'imagine que le contexte est plus complexe, mais pourquoi ne pas mettre le code d'init dans le constructeur de NewObject et celui de destroy dans son destructeur ?
Parce que j'essaie de surcharger new, new[], delete, delete[] via un malloc & free, afin d'essayer de créer un memory manager et qu'à ce moment là, le new n'appellera plus le constructeur de la classe que j'instancie.
Voilà pourquoi un init et un destroy.
Horst Kraemer
On Fri, 15 Apr 2005 13:32:58 +0200, Stephane Wirtel wrote:
Voici un problème qui m'ennuie à cause de l'héritage et du polymorphisme.
J'ai créé la classe abstraite Object avec les méthodes init et destroy comme étant virtuelle pure.
Je crée la class NewObject à partir d'Object et j'implémente donc init et destroy afin de pouvoir instancier un objet de la classe NewObject.
normalement, "this" représente l'objet dynamique, donc, normalement this->init () se trouvant dans Object devrait faire appel à NewObject::init et non à Object::init.
Est-ce que je me trompe ?
Normalement - à l'exceptions de constructeurs et de destructeurs. Dans un constucteur ou dans un destructeur *this a toujours le type statique de la classe à laquelle ce dtor|ctor appartient, donc init() dans Object::Object appelle toujours Object::init
C´est une des petites differences entre C++ et Delphi (Object Pascal). En Delphi c'est le constructeur FILS qui appelle le constructuer PERE (inherited init) dans son code. En C++ le constructeur FILS est appelé par le système avant l'exécution du constructeur FILS, c.a.d. en Delphi l'objet a déjà le type FILS quand le constructeur de PERE est appelé, tandis qu'en C++ l´objet a encore de type PERE quand le constructeur de PERE est appelè.
Voici un problème qui m'ennuie à cause de l'héritage et du polymorphisme.
J'ai créé la classe abstraite Object avec les méthodes init et destroy
comme étant virtuelle pure.
Je crée la class NewObject à partir d'Object et j'implémente donc init et destroy
afin de pouvoir instancier un objet de la classe NewObject.
normalement, "this" représente l'objet dynamique, donc, normalement this->init () se trouvant
dans Object devrait faire appel à NewObject::init et non à Object::init.
Est-ce que je me trompe ?
Normalement - à l'exceptions de constructeurs et de destructeurs. Dans
un constucteur ou dans un destructeur *this a toujours le type
statique de la classe à laquelle ce dtor|ctor appartient, donc init()
dans Object::Object appelle toujours Object::init
C´est une des petites differences entre C++ et Delphi (Object Pascal).
En Delphi c'est le constructeur FILS qui appelle le constructuer PERE
(inherited init) dans son code. En C++ le constructeur FILS est appelé
par le système avant l'exécution du constructeur FILS, c.a.d. en
Delphi l'objet a déjà le type FILS quand le constructeur de PERE est
appelé, tandis qu'en C++ l´objet a encore de type PERE quand le
constructeur de PERE est appelè.
On Fri, 15 Apr 2005 13:32:58 +0200, Stephane Wirtel wrote:
Voici un problème qui m'ennuie à cause de l'héritage et du polymorphisme.
J'ai créé la classe abstraite Object avec les méthodes init et destroy comme étant virtuelle pure.
Je crée la class NewObject à partir d'Object et j'implémente donc init et destroy afin de pouvoir instancier un objet de la classe NewObject.
normalement, "this" représente l'objet dynamique, donc, normalement this->init () se trouvant dans Object devrait faire appel à NewObject::init et non à Object::init.
Est-ce que je me trompe ?
Normalement - à l'exceptions de constructeurs et de destructeurs. Dans un constucteur ou dans un destructeur *this a toujours le type statique de la classe à laquelle ce dtor|ctor appartient, donc init() dans Object::Object appelle toujours Object::init
C´est une des petites differences entre C++ et Delphi (Object Pascal). En Delphi c'est le constructeur FILS qui appelle le constructuer PERE (inherited init) dans son code. En C++ le constructeur FILS est appelé par le système avant l'exécution du constructeur FILS, c.a.d. en Delphi l'objet a déjà le type FILS quand le constructeur de PERE est appelé, tandis qu'en C++ l´objet a encore de type PERE quand le constructeur de PERE est appelè.
-- Horst
Alexandre
normalement, "this" représente l'objet dynamique, donc, normalement this->init () se trouvant dans Object devrait faire appel à NewObject::init et non à Object::init.
Mais Object::init n'est pas appelable car virtuelle pure. Tu as un message du type "Pure virtual fonction call" ?
normalement, "this" représente l'objet dynamique, donc, normalement
this->init () se trouvant
dans Object devrait faire appel à NewObject::init et non à Object::init.
Mais Object::init n'est pas appelable car virtuelle pure. Tu as un message
du type "Pure virtual fonction call" ?
normalement, "this" représente l'objet dynamique, donc, normalement this->init () se trouvant dans Object devrait faire appel à NewObject::init et non à Object::init.
Mais Object::init n'est pas appelable car virtuelle pure. Tu as un message du type "Pure virtual fonction call" ?
J'imagine que le contexte est plus complexe, mais pourquoi ne pas mettre le code d'init dans le constructeur de NewObject et celui de destroy dans son destructeur ? Parce que j'essaie de surcharger new, new[], delete, delete[] via un
malloc & free, afin d'essayer de créer un memory manager et qu'à ce moment là, le new n'appellera plus le constructeur de la classe que j'instancie. Voilà pourquoi un init et un destroy.
???
Comprends pas... Tu veux dire que dans le programme suivant : _______________________________________________________________________________ #include <iostream> #include <ostream> #include <cstdlib> #include <cassert>
class B { protected: int i; public: B(int i) : i(i) { std::cout << "B::B (" << i << ") at " << this << 'n'; } virtual ~B() { std::cout << "B::~B(" << i << ") at " << this << 'n'; } }; // class B
class D : public B { public: D(int i) : B(i) { std::cout << "D::D (" << i << ") at " << this << 'n'; } ~D() { std::cout << "D::~D(" << i << ") at " << this << 'n'; } }; // class D
int main() { delete new D(42); return 0; } // main() _______________________________________________________________________________
les constructeurs et destructeurs ne sont pas appelés ? (Il peut arriver que le destructeur de D n'est pas appelé si on oublie de rendre le destructeur de B virtuel [ => comportement indéfini], mais cela n'a rien à voir avec la redéfinition de new et delete.) Chez moi cela affiche _________________________________ operator new(8) returns 0xa050278 B::B (42) at 0xa050278 D::D (42) at 0xa050278 D::~D(42) at 0xa050278 B::~B(42) at 0xa050278 operator delete(0xa050278) _________________________________
Falk
Stephane Wirtel wrote:
J'imagine que le contexte est plus complexe, mais pourquoi ne pas
mettre le code d'init dans le constructeur de NewObject et celui de
destroy dans son destructeur ?
Parce que j'essaie de surcharger new, new[], delete, delete[] via un
malloc & free, afin d'essayer de créer un memory manager
et qu'à ce moment là, le new n'appellera plus le constructeur de la
classe que j'instancie.
Voilà pourquoi un init et un destroy.
???
Comprends pas...
Tu veux dire que dans le programme suivant :
_______________________________________________________________________________
#include <iostream>
#include <ostream>
#include <cstdlib>
#include <cassert>
class B
{
protected:
int i;
public:
B(int i) : i(i) { std::cout << "B::B (" << i << ") at " << this << 'n'; }
virtual ~B() { std::cout << "B::~B(" << i << ") at " << this << 'n'; }
}; // class B
class D : public B
{
public:
D(int i) : B(i) { std::cout << "D::D (" << i << ") at " << this << 'n'; }
~D() { std::cout << "D::~D(" << i << ") at " << this << 'n'; }
}; // class D
int main()
{
delete new D(42);
return 0;
} // main()
_______________________________________________________________________________
les constructeurs et destructeurs ne sont pas appelés ? (Il peut arriver que
le destructeur de D n'est pas appelé si on oublie de rendre le destructeur
de B virtuel [ => comportement indéfini], mais cela n'a rien à voir avec la
redéfinition de new et delete.)
Chez moi cela affiche
_________________________________
operator new(8) returns 0xa050278
B::B (42) at 0xa050278
D::D (42) at 0xa050278
D::~D(42) at 0xa050278
B::~B(42) at 0xa050278
operator delete(0xa050278)
_________________________________
J'imagine que le contexte est plus complexe, mais pourquoi ne pas mettre le code d'init dans le constructeur de NewObject et celui de destroy dans son destructeur ? Parce que j'essaie de surcharger new, new[], delete, delete[] via un
malloc & free, afin d'essayer de créer un memory manager et qu'à ce moment là, le new n'appellera plus le constructeur de la classe que j'instancie. Voilà pourquoi un init et un destroy.
???
Comprends pas... Tu veux dire que dans le programme suivant : _______________________________________________________________________________ #include <iostream> #include <ostream> #include <cstdlib> #include <cassert>
class B { protected: int i; public: B(int i) : i(i) { std::cout << "B::B (" << i << ") at " << this << 'n'; } virtual ~B() { std::cout << "B::~B(" << i << ") at " << this << 'n'; } }; // class B
class D : public B { public: D(int i) : B(i) { std::cout << "D::D (" << i << ") at " << this << 'n'; } ~D() { std::cout << "D::~D(" << i << ") at " << this << 'n'; } }; // class D
int main() { delete new D(42); return 0; } // main() _______________________________________________________________________________
les constructeurs et destructeurs ne sont pas appelés ? (Il peut arriver que le destructeur de D n'est pas appelé si on oublie de rendre le destructeur de B virtuel [ => comportement indéfini], mais cela n'a rien à voir avec la redéfinition de new et delete.) Chez moi cela affiche _________________________________ operator new(8) returns 0xa050278 B::B (42) at 0xa050278 D::D (42) at 0xa050278 D::~D(42) at 0xa050278 B::~B(42) at 0xa050278 operator delete(0xa050278) _________________________________
Falk
Thomas Labourdette
Franck Branjonneau a écrit le Vendredi 15 Avril 2005 23:09 :
"Alexandre" écrivait:
le destructeur doit être virtuel ici.
Pourquoi ?
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé. Comme dans : { Object *p=new DerivedObject(); delete p; }
@+ -- Heinrich IDÉKI-LAHULA (nordiste) (signature aléatoire) " L'église est proche, mais la route est verglacée. Le bar est loin, mais je marcherai avec prudence. " (Proverbe russe)
Franck Branjonneau a écrit le Vendredi 15 Avril 2005 23:09 :
"Alexandre" <alex.g@netcourrier.com> écrivait:
le destructeur doit être virtuel ici.
Pourquoi ?
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé.
Comme dans :
{
Object *p=new DerivedObject();
delete p;
}
@+
--
Heinrich IDÉKI-LAHULA (nordiste) (signature aléatoire)
" L'église est proche, mais la route est verglacée. Le bar est loin,
mais je marcherai avec prudence. " (Proverbe russe)
Franck Branjonneau a écrit le Vendredi 15 Avril 2005 23:09 :
"Alexandre" écrivait:
le destructeur doit être virtuel ici.
Pourquoi ?
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé. Comme dans : { Object *p=new DerivedObject(); delete p; }
@+ -- Heinrich IDÉKI-LAHULA (nordiste) (signature aléatoire) " L'église est proche, mais la route est verglacée. Le bar est loin, mais je marcherai avec prudence. " (Proverbe russe)
James Kanze
Thomas Labourdette wrote:
Franck Branjonneau a écrit le Vendredi 15 Avril 2005 23:09 :
"Alexandre" écrivait:
le destructeur doit être virtuel ici.
Pourquoi ?
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé. Comme dans : { Object *p=new DerivedObject(); delete p; }
Parce qu'autrement, c'est un comportement indéfini. Qui éventuellement provoque un crash du programme.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Thomas Labourdette wrote:
Franck Branjonneau a écrit le Vendredi 15 Avril 2005 23:09 :
"Alexandre" <alex.g@netcourrier.com> écrivait:
le destructeur doit être virtuel ici.
Pourquoi ?
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé.
Comme dans :
{
Object *p=new DerivedObject();
delete p;
}
Parce qu'autrement, c'est un comportement indéfini. Qui
éventuellement provoque un crash du programme.
--
James Kanze mailto: james.kanze@free.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Franck Branjonneau a écrit le Vendredi 15 Avril 2005 23:09 :
"Alexandre" écrivait:
le destructeur doit être virtuel ici.
Pourquoi ?
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé. Comme dans : { Object *p=new DerivedObject(); delete p; }
Parce qu'autrement, c'est un comportement indéfini. Qui éventuellement provoque un crash du programme.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Franck Branjonneau
James Kanze écrivait:
Thomas Labourdette wrote:
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé. Comme dans : { Object *p=new DerivedObject(); delete p; }
Parce qu'autrement, c'est un comportement indéfini. Qui éventuellement provoque un crash du programme.
Comme rappelé par Falk, oui. Mais le code de l'OP était :
struct B {
virtual void foo() { // Faire quelque chose }
};
struct D:B {
virtual void foo() { // Faire autre chose }
};
int main() {
D obj; // J'ajoute B & ref_obj(obj); }
J'ai un comportement indéfini là ? Pourquoi, le cas échéant ? -- Franck Branjonneau
James Kanze <kanze@none> écrivait:
Thomas Labourdette wrote:
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé.
Comme dans :
{
Object *p=new DerivedObject();
delete p;
}
Parce qu'autrement, c'est un comportement indéfini. Qui
éventuellement provoque un crash du programme.
Comme rappelé par Falk, oui. Mais le code de l'OP était :
struct B {
virtual void foo() { // Faire quelque chose }
};
struct D:B {
virtual void foo() { // Faire autre chose }
};
int
main() {
D obj;
// J'ajoute
B & ref_obj(obj);
}
J'ai un comportement indéfini là ? Pourquoi, le cas échéant ?
--
Franck Branjonneau <fasbjx@free.fr>
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé. Comme dans : { Object *p=new DerivedObject(); delete p; }
Parce qu'autrement, c'est un comportement indéfini. Qui éventuellement provoque un crash du programme.
Comme rappelé par Falk, oui. Mais le code de l'OP était :
struct B {
virtual void foo() { // Faire quelque chose }
};
struct D:B {
virtual void foo() { // Faire autre chose }
};
int main() {
D obj; // J'ajoute B & ref_obj(obj); }
J'ai un comportement indéfini là ? Pourquoi, le cas échéant ? -- Franck Branjonneau
kanze
Franck Branjonneau wrote:
James Kanze écrivait:
Thomas Labourdette wrote:
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé.
Comme dans : { Object *p=new DerivedObject(); delete p; }
Parce qu'autrement, c'est un comportement indéfini. Qui éventuellement provoque un crash du programme.
Comme rappelé par Falk, oui.
Je n'avais pas vu tout le thread. Je répondais seulement à une assertation fausse. Il n'y a aucune garantie que le destructeur de l'objet de base serait appelé, et surtout, ce n'est pas le seul effet désagréable.
Mais le code de l'OP était :
struct B {
virtual void foo() { // Faire quelque chose }
};
struct D:B {
virtual void foo() { // Faire autre chose }
};
int main() {
D obj; // J'ajoute B & ref_obj(obj); }
J'ai un comportement indéfini là ? Pourquoi, le cas échéant ?
Je n'avais pas vu le thread avant, mais maintenant que je l'ai vu, ce n'était pas ça le code de l'OP. Le code de l'OP avait une fonction virtuelle pûre, qu'on appelait dans le constructeur de la classe de base. Donc aussi un comportement indéfini.
-- 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
Franck Branjonneau wrote:
James Kanze <kanze@none> écrivait:
Thomas Labourdette wrote:
parcequ'autrement c'est le destructeur de l'objet de base
qui est appelé.
Comme dans :
{
Object *p=new DerivedObject();
delete p;
}
Parce qu'autrement, c'est un comportement indéfini. Qui
éventuellement provoque un crash du programme.
Comme rappelé par Falk, oui.
Je n'avais pas vu tout le thread. Je répondais seulement à une
assertation fausse. Il n'y a aucune garantie que le destructeur
de l'objet de base serait appelé, et surtout, ce n'est pas le
seul effet désagréable.
Mais le code de l'OP était :
struct B {
virtual void foo() { // Faire quelque chose }
};
struct D:B {
virtual void foo() { // Faire autre chose }
};
int
main() {
D obj;
// J'ajoute
B & ref_obj(obj);
}
J'ai un comportement indéfini là ? Pourquoi, le cas échéant ?
Je n'avais pas vu le thread avant, mais maintenant que je l'ai
vu, ce n'était pas ça le code de l'OP. Le code de l'OP avait une
fonction virtuelle pûre, qu'on appelait dans le constructeur de
la classe de base. Donc aussi un comportement indéfini.
--
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
parcequ'autrement c'est le destructeur de l'objet de base qui est appelé.
Comme dans : { Object *p=new DerivedObject(); delete p; }
Parce qu'autrement, c'est un comportement indéfini. Qui éventuellement provoque un crash du programme.
Comme rappelé par Falk, oui.
Je n'avais pas vu tout le thread. Je répondais seulement à une assertation fausse. Il n'y a aucune garantie que le destructeur de l'objet de base serait appelé, et surtout, ce n'est pas le seul effet désagréable.
Mais le code de l'OP était :
struct B {
virtual void foo() { // Faire quelque chose }
};
struct D:B {
virtual void foo() { // Faire autre chose }
};
int main() {
D obj; // J'ajoute B & ref_obj(obj); }
J'ai un comportement indéfini là ? Pourquoi, le cas échéant ?
Je n'avais pas vu le thread avant, mais maintenant que je l'ai vu, ce n'était pas ça le code de l'OP. Le code de l'OP avait une fonction virtuelle pûre, qu'on appelait dans le constructeur de la classe de base. Donc aussi un comportement indéfini.
-- 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