class toto
{
public:
toto();
int b;
void tata();
};
toto::toto()
{
b = 4;
}
void toto::tata()
{
}
class titi: toto
{
public:
void go();
};
void titi::go()
{
cout << "ok" << b << endl;
}
int main(int argc, char *argv[])
{
toto* toto1 = new toto();
titi *titi1 = (titi*) toto1;
titi1->go();
return 0;
}
PS: Je n'ai pas envie de rajouter une fonction virtuelle go() à toto
(en fait, je ne le peux pas, toto étant une librairie à laquelle je n'ai
pas accès).
< < // Ça, c'est impossible : si on peut convertir un "Derivee*" en <"Base*", l'inverse n'est pas possible ! <
--> Par quel miracle le code que j'ai mis dans ce post marche alors!!! ? Etrange... Dommage que tu dises que c'est impossible, ca me rendrait pourtant bien service car c'est plus "propre" que de faire une fonction à laquelle je passe une instance de Base en entrée et qui fasse le traitement de go(); on perd l'intérêt de l'objet...
J'aimerais bien utiliser le code que tu proposes, mais j'ai directement une instance de Derivee, je suis un peu bloqué avec ta soluce...
Cordialement, Olivier.
Fabien LE LEZ wrote:
On Thu, 26 May 2005 17:29:41 +0200, olivier :
Bon, les "toto" et "titi" c'est bien joli, mais pour savoir qui est dérivé de qui, accroche-toi...
Je me permets donc de modifier ton code, tout en le corrigeant à mesure :
class Base { public: Base() : b (4) {}
int b; // Normalement, ce genre de truc est privé, mais bon...
void foo() {}
virtual ~Base() {} // Si "Base" n'a pas de destructeur virtuel, ça veut dire qu'elle n'est pas prévue pour être dérivée. };
class titi: toto // T'es sûr de vouloir un héritage privé ?
class Derivee: public Base { public: void go() { cout << "ok" << b << endl; } };
int main() { Base* ptr_base= new Base;
Derivee* ptr_derivee= [...] ptr_base; // Ça, c'est impossible : si on peut convertir un "Derivee*" en "Base*", l'inverse n'est pas possible ! }
Supposons que tu aies une fonction f qui crée un Derivee* mais renvoie un Base* :
<
< // Ça, c'est impossible : si on peut convertir un "Derivee*" en
<"Base*", l'inverse n'est pas possible !
<
--> Par quel miracle le code que j'ai mis dans ce post marche alors!!! ?
Etrange...
Dommage que tu dises que c'est impossible, ca me rendrait pourtant bien
service car c'est plus "propre" que de faire une fonction à laquelle je
passe une instance de Base en entrée et qui fasse le traitement de go();
on perd l'intérêt de l'objet...
J'aimerais bien utiliser le code que tu proposes, mais j'ai directement
une instance de Derivee, je suis un peu bloqué avec ta soluce...
Cordialement,
Olivier.
Fabien LE LEZ wrote:
On Thu, 26 May 2005 17:29:41 +0200, olivier <nospam@nospam.com>:
Bon, les "toto" et "titi" c'est bien joli, mais pour savoir qui est
dérivé de qui, accroche-toi...
Je me permets donc de modifier ton code, tout en le corrigeant à
mesure :
class Base
{
public:
Base() : b (4) {}
int b; // Normalement, ce genre de truc est privé, mais bon...
void foo() {}
virtual ~Base() {}
// Si "Base" n'a pas de destructeur virtuel, ça veut dire
qu'elle n'est pas prévue pour être dérivée.
};
class titi: toto
// T'es sûr de vouloir un héritage privé ?
class Derivee: public Base
{
public:
void go() { cout << "ok" << b << endl; }
};
int main()
{
Base* ptr_base= new Base;
Derivee* ptr_derivee= [...] ptr_base;
// Ça, c'est impossible : si on peut convertir un "Derivee*" en
"Base*", l'inverse n'est pas possible !
}
Supposons que tu aies une fonction f qui crée un Derivee* mais renvoie
un Base* :
< < // Ça, c'est impossible : si on peut convertir un "Derivee*" en <"Base*", l'inverse n'est pas possible ! <
--> Par quel miracle le code que j'ai mis dans ce post marche alors!!! ? Etrange... Dommage que tu dises que c'est impossible, ca me rendrait pourtant bien service car c'est plus "propre" que de faire une fonction à laquelle je passe une instance de Base en entrée et qui fasse le traitement de go(); on perd l'intérêt de l'objet...
J'aimerais bien utiliser le code que tu proposes, mais j'ai directement une instance de Derivee, je suis un peu bloqué avec ta soluce...
Cordialement, Olivier.
Fabien LE LEZ wrote:
On Thu, 26 May 2005 17:29:41 +0200, olivier :
Bon, les "toto" et "titi" c'est bien joli, mais pour savoir qui est dérivé de qui, accroche-toi...
Je me permets donc de modifier ton code, tout en le corrigeant à mesure :
class Base { public: Base() : b (4) {}
int b; // Normalement, ce genre de truc est privé, mais bon...
void foo() {}
virtual ~Base() {} // Si "Base" n'a pas de destructeur virtuel, ça veut dire qu'elle n'est pas prévue pour être dérivée. };
class titi: toto // T'es sûr de vouloir un héritage privé ?
class Derivee: public Base { public: void go() { cout << "ok" << b << endl; } };
int main() { Base* ptr_base= new Base;
Derivee* ptr_derivee= [...] ptr_base; // Ça, c'est impossible : si on peut convertir un "Derivee*" en "Base*", l'inverse n'est pas possible ! }
Supposons que tu aies une fonction f qui crée un Derivee* mais renvoie un Base* :
Tout est là : http://www.giromini.org/usenet-fr/repondre.html
Effectivement, désolé pour la mise en forme!
Bon, je n'ai toujours pas compris pourquoi mon code marche... Merci en tout cas pour vos éclaircissements.
Cordialement, Olivier.
Cyrille
Merci pour toutes ces infos.
< < // Ça, c'est impossible : si on peut convertir un "Derivee*" en <"Base*", l'inverse n'est pas possible ! <
--> Par quel miracle le code que j'ai mis dans ce post marche alors!!! ? Etrange...
Faudrait savoir, tu disais qu'il ne marchait pas toujours. Là, tu essayes d'utiliser un objet Base comme si c'était un autre objet. Le comportement d'un tel truc est sans doute indéfini. Ca "marche" parfois et d'autre fois non, selon le sens du vent, du compilateur et du système.
Dommage que tu dises que c'est impossible, ca me rendrait pourtant bien service car c'est plus "propre" que de faire une fonction à laquelle je passe une instance de Base en entrée et qui fasse le traitement de go(); on perd l'intérêt de l'objet...
J'aimerais bien utiliser le code que tu proposes, mais j'ai directement une instance de Derivee, je suis un peu bloqué avec ta soluce...
Bon, en gros, tu voudrais étendre les fonctionnalités d'une classe que tu ne peux pas modifier. Je suppose qu'il y a une bonne raison pour laquelle tu ne peux pas écrire "new Derivee()" directement. Tu ne veux pas utiliser une fonction libre parce que ça ne fait pas assez objet, bon pourquoi pas.
Alors il y a ça: class Box { public: Box ( toto * t) : m_toto( t ) {}
// tu utilises comme ça: int main(int argc, char *argv[]) { toto* toto1 = new toto(); Box boite(toto1); boite.go(); }
PS: j'appelle la classe Box et son instance boite mais ça ne correspond pas à quelque chose, je manquais simplement d'imagination. PS(2): faudra pas oublier de faire un delete sur l'instance de toto, hein. Pour bien faire, on peut utiliser boost::shared_pointer, pour être sûr que Box ne contient pas à un moment un pointeur vers un objet détruit.
-- win the yes need the no to win against the no!
Merci pour toutes ces infos.
<
< // Ça, c'est impossible : si on peut convertir un "Derivee*" en
<"Base*", l'inverse n'est pas possible !
<
--> Par quel miracle le code que j'ai mis dans ce post marche alors!!! ?
Etrange...
Faudrait savoir, tu disais qu'il ne marchait pas toujours.
Là, tu essayes d'utiliser un objet Base comme si c'était un autre objet.
Le comportement d'un tel truc est sans doute indéfini. Ca "marche"
parfois et d'autre fois non, selon le sens du vent, du compilateur et du
système.
Dommage que tu dises que c'est impossible, ca me rendrait pourtant bien
service car c'est plus "propre" que de faire une fonction à laquelle je
passe une instance de Base en entrée et qui fasse le traitement de go();
on perd l'intérêt de l'objet...
J'aimerais bien utiliser le code que tu proposes, mais j'ai directement
une instance de Derivee, je suis un peu bloqué avec ta soluce...
Bon, en gros, tu voudrais étendre les fonctionnalités d'une classe que
tu ne peux pas modifier.
Je suppose qu'il y a une bonne raison pour laquelle tu ne peux pas
écrire "new Derivee()" directement.
Tu ne veux pas utiliser une fonction libre parce que ça ne fait pas
assez objet, bon pourquoi pas.
Alors il y a ça:
class Box
{
public:
Box ( toto * t) : m_toto( t ) {}
// tu utilises comme ça:
int main(int argc, char *argv[])
{
toto* toto1 = new toto();
Box boite(toto1);
boite.go();
}
PS: j'appelle la classe Box et son instance boite mais ça ne correspond
pas à quelque chose, je manquais simplement d'imagination.
PS(2): faudra pas oublier de faire un delete sur l'instance de toto,
hein. Pour bien faire, on peut utiliser boost::shared_pointer, pour être
sûr que Box ne contient pas à un moment un pointeur vers un objet détruit.
< < // Ça, c'est impossible : si on peut convertir un "Derivee*" en <"Base*", l'inverse n'est pas possible ! <
--> Par quel miracle le code que j'ai mis dans ce post marche alors!!! ? Etrange...
Faudrait savoir, tu disais qu'il ne marchait pas toujours. Là, tu essayes d'utiliser un objet Base comme si c'était un autre objet. Le comportement d'un tel truc est sans doute indéfini. Ca "marche" parfois et d'autre fois non, selon le sens du vent, du compilateur et du système.
Dommage que tu dises que c'est impossible, ca me rendrait pourtant bien service car c'est plus "propre" que de faire une fonction à laquelle je passe une instance de Base en entrée et qui fasse le traitement de go(); on perd l'intérêt de l'objet...
J'aimerais bien utiliser le code que tu proposes, mais j'ai directement une instance de Derivee, je suis un peu bloqué avec ta soluce...
Bon, en gros, tu voudrais étendre les fonctionnalités d'une classe que tu ne peux pas modifier. Je suppose qu'il y a une bonne raison pour laquelle tu ne peux pas écrire "new Derivee()" directement. Tu ne veux pas utiliser une fonction libre parce que ça ne fait pas assez objet, bon pourquoi pas.
Alors il y a ça: class Box { public: Box ( toto * t) : m_toto( t ) {}
// tu utilises comme ça: int main(int argc, char *argv[]) { toto* toto1 = new toto(); Box boite(toto1); boite.go(); }
PS: j'appelle la classe Box et son instance boite mais ça ne correspond pas à quelque chose, je manquais simplement d'imagination. PS(2): faudra pas oublier de faire un delete sur l'instance de toto, hein. Pour bien faire, on peut utiliser boost::shared_pointer, pour être sûr que Box ne contient pas à un moment un pointeur vers un objet détruit.
-- win the yes need the no to win against the no!
Cyrille
Fabien LE LEZ wrote:
Tout est là : http://www.giromini.org/usenet-fr/repondre.html
Effectivement, désolé pour la mise en forme!
Bon, je n'ai toujours pas compris pourquoi mon code marche...
Ca "marche" parce que le cast dans le style du C est permissif, permettant de convertir un pointeur de la base vers un pointeur de la dérivée quelque soit le vrai type de l'objet. Pour éviter ce genre de trucs, utilisez dynamic_cast<>, qui lancera une exception std::bad_cast dans ce genre de cas.
-- win the yes need the no to win against the no!
Fabien LE LEZ wrote:
Tout est là : http://www.giromini.org/usenet-fr/repondre.html
Effectivement, désolé pour la mise en forme!
Bon, je n'ai toujours pas compris pourquoi mon code marche...
Ca "marche" parce que le cast dans le style du C est permissif,
permettant de convertir un pointeur de la base vers un pointeur de la
dérivée quelque soit le vrai type de l'objet. Pour éviter ce genre de
trucs, utilisez dynamic_cast<>, qui lancera une exception std::bad_cast
dans ce genre de cas.
Tout est là : http://www.giromini.org/usenet-fr/repondre.html
Effectivement, désolé pour la mise en forme!
Bon, je n'ai toujours pas compris pourquoi mon code marche...
Ca "marche" parce que le cast dans le style du C est permissif, permettant de convertir un pointeur de la base vers un pointeur de la dérivée quelque soit le vrai type de l'objet. Pour éviter ce genre de trucs, utilisez dynamic_cast<>, qui lancera une exception std::bad_cast dans ce genre de cas.
-- win the yes need the no to win against the no!
olivier
Cyrille wrote:
Faudrait savoir, tu disais qu'il ne marchait pas toujours. Là, tu essayes d'utiliser un objet Base comme si c'était un autre objet. Le comportement d'un tel truc est sans doute indéfini. Ca "marche" parfois et d'autre fois non, selon le sens du vent, du compilateur et du système.
En fait ca marche toujours dans le code que j'ai posté. Ca plante toujours dans un autre code plus complexe (et encore, je ne suis pas sûr que le plantage vienne de là).
Faudrait que je regarde avec gvd pour comprendre vraiment ce qui se passe...
Bon, en gros, tu voudrais étendre les fonctionnalités d'une classe que tu ne peux pas modifier. Je suppose qu'il y a une bonne raison pour laquelle tu ne peux pas écrire "new Derivee()" directement. Tu ne veux pas utiliser une fonction libre parce que ça ne fait pas assez objet, bon pourquoi pas.
Alors il y a ça: class Box { public: Box ( toto * t) : m_toto( t ) {}
// tu utilises comme ça: int main(int argc, char *argv[]) { toto* toto1 = new toto(); Box boite(toto1); boite.go(); }
PS: j'appelle la classe Box et son instance boite mais ça ne correspond pas à quelque chose, je manquais simplement d'imagination. PS(2): faudra pas oublier de faire un delete sur l'instance de toto, hein. Pour bien faire, on peut utiliser boost::shared_pointer, pour être sûr que Box ne contient pas à un moment un pointeur vers un objet détruit.
C'est effectivement peut-être le meilleur compromis.
Merci Olivier.
Cyrille wrote:
Faudrait savoir, tu disais qu'il ne marchait pas toujours.
Là, tu essayes d'utiliser un objet Base comme si c'était un autre objet.
Le comportement d'un tel truc est sans doute indéfini. Ca "marche"
parfois et d'autre fois non, selon le sens du vent, du compilateur et du
système.
En fait ca marche toujours dans le code que j'ai posté. Ca plante
toujours dans un autre code plus complexe (et encore, je ne suis pas sûr
que le plantage vienne de là).
Faudrait que je regarde avec gvd pour comprendre vraiment ce qui se passe...
Bon, en gros, tu voudrais étendre les fonctionnalités d'une classe que
tu ne peux pas modifier.
Je suppose qu'il y a une bonne raison pour laquelle tu ne peux pas
écrire "new Derivee()" directement.
Tu ne veux pas utiliser une fonction libre parce que ça ne fait pas
assez objet, bon pourquoi pas.
Alors il y a ça:
class Box
{
public:
Box ( toto * t) : m_toto( t ) {}
// tu utilises comme ça:
int main(int argc, char *argv[])
{
toto* toto1 = new toto();
Box boite(toto1);
boite.go();
}
PS: j'appelle la classe Box et son instance boite mais ça ne correspond
pas à quelque chose, je manquais simplement d'imagination.
PS(2): faudra pas oublier de faire un delete sur l'instance de toto,
hein. Pour bien faire, on peut utiliser boost::shared_pointer, pour être
sûr que Box ne contient pas à un moment un pointeur vers un objet détruit.
C'est effectivement peut-être le meilleur compromis.
Faudrait savoir, tu disais qu'il ne marchait pas toujours. Là, tu essayes d'utiliser un objet Base comme si c'était un autre objet. Le comportement d'un tel truc est sans doute indéfini. Ca "marche" parfois et d'autre fois non, selon le sens du vent, du compilateur et du système.
En fait ca marche toujours dans le code que j'ai posté. Ca plante toujours dans un autre code plus complexe (et encore, je ne suis pas sûr que le plantage vienne de là).
Faudrait que je regarde avec gvd pour comprendre vraiment ce qui se passe...
Bon, en gros, tu voudrais étendre les fonctionnalités d'une classe que tu ne peux pas modifier. Je suppose qu'il y a une bonne raison pour laquelle tu ne peux pas écrire "new Derivee()" directement. Tu ne veux pas utiliser une fonction libre parce que ça ne fait pas assez objet, bon pourquoi pas.
Alors il y a ça: class Box { public: Box ( toto * t) : m_toto( t ) {}
// tu utilises comme ça: int main(int argc, char *argv[]) { toto* toto1 = new toto(); Box boite(toto1); boite.go(); }
PS: j'appelle la classe Box et son instance boite mais ça ne correspond pas à quelque chose, je manquais simplement d'imagination. PS(2): faudra pas oublier de faire un delete sur l'instance de toto, hein. Pour bien faire, on peut utiliser boost::shared_pointer, pour être sûr que Box ne contient pas à un moment un pointeur vers un objet détruit.
C'est effectivement peut-être le meilleur compromis.
Merci Olivier.
Fabien LE LEZ
On Thu, 26 May 2005 18:26:00 +0200, olivier :
Bon, je n'ai toujours pas compris pourquoi mon code marche...
Qu'entends-tu par "marcher" exactement ? Ça compile parce qu'un compilo C++ est très permissif, et accepte de compiler beaucoup de conneries. Si le programme a le comportement que tu attendais sur ton PC avec telle version de tel compilateur, c'est plus par hasard qu'autre chose.
On Thu, 26 May 2005 18:26:00 +0200, olivier <nospam@nospam.com>:
Bon, je n'ai toujours pas compris pourquoi mon code marche...
Qu'entends-tu par "marcher" exactement ?
Ça compile parce qu'un compilo C++ est très permissif, et accepte de
compiler beaucoup de conneries.
Si le programme a le comportement que tu attendais sur ton PC avec
telle version de tel compilateur, c'est plus par hasard qu'autre
chose.
Bon, je n'ai toujours pas compris pourquoi mon code marche...
Qu'entends-tu par "marcher" exactement ? Ça compile parce qu'un compilo C++ est très permissif, et accepte de compiler beaucoup de conneries. Si le programme a le comportement que tu attendais sur ton PC avec telle version de tel compilateur, c'est plus par hasard qu'autre chose.
Fabien LE LEZ
On Thu, 26 May 2005 18:29:26 +0200, Cyrille :
int main(int argc, char *argv[]) { toto* toto1 = new toto(); Box boite(toto1);
Généralement, c'est la classe Box qui s'occupe d'allouer, puis détruire, *toto1.
On Thu, 26 May 2005 18:29:26 +0200, Cyrille <cyrille@frsf.invalid>:
int main(int argc, char *argv[])
{
toto* toto1 = new toto();
Box boite(toto1);
Généralement, c'est la classe Box qui s'occupe d'allouer, puis
détruire, *toto1.
int main(int argc, char *argv[]) { toto* toto1 = new toto(); Box boite(toto1);
Généralement, c'est la classe Box qui s'occupe d'allouer, puis détruire, *toto1.
Horst Kraemer
olivier wrote:
Le code suivant marche pas toujours, pouvez-vous me donner la bonne façon de le coder:
class toto { public: toto(); int b; void tata(); };
class titi: toto { public: void go(); };
void titi::go() { cout << "ok" << b << endl; }
int main(int argc, char *argv[]) { toto* toto1 = new toto(); titi *titi1 = (titi*) toto1; titi1->go(); return 0; }
PS: Je n'ai pas envie de rajouter une fonction virtuelle go() à toto (en fait, je ne le peux pas, toto étant une librairie à laquelle je n'ai pas accès).
Le problème est que ce code ne fonctionne que par hasard s'il a l'air de fonctionner. La norme du langage C++ dit que le comportement de ton programme est indéfini - cela veut dire tout simplement que le programme n'a pas de sens. C'est une pure perte de temps de vouloir savoir le *pourquoi*. C'est un programme contre le langage....
Une facon légale de faire marcher le programme est de créer "on the fly" un objet titi à partir de ton toto qui utilise pour sa construction un constructeur de copie toto(const toto&)
class titi: toto { public: titi(const toto& t) : toto(t) {} void go() { cout << "ok" << b << endl; } };
int main() { toto* toto1 = new toto(); titi(*toto1).go(); // ou bien titi* titi1 = new titi(*toto1); titi1->go(); return 0; }
-- Horst
-- Lâche pas la patate!
olivier <nospam@nospam.com> wrote:
Le code suivant marche pas toujours, pouvez-vous me donner la bonne
façon de le coder:
class toto
{
public:
toto();
int b;
void tata();
};
class titi: toto
{
public:
void go();
};
void titi::go()
{
cout << "ok" << b << endl;
}
int main(int argc, char *argv[])
{
toto* toto1 = new toto();
titi *titi1 = (titi*) toto1;
titi1->go();
return 0;
}
PS: Je n'ai pas envie de rajouter une fonction virtuelle go() à toto
(en fait, je ne le peux pas, toto étant une librairie à laquelle je n'ai
pas accès).
Le problème est que ce code ne fonctionne que par hasard s'il a l'air
de fonctionner. La norme du langage C++ dit que le comportement de ton
programme est indéfini - cela veut dire tout simplement que le
programme n'a pas de sens. C'est une pure perte de temps de vouloir
savoir le *pourquoi*. C'est un programme contre le langage....
Une facon légale de faire marcher le programme est de créer "on the
fly" un objet titi à partir de ton toto qui utilise pour sa
construction un constructeur de copie toto(const toto&)
class titi: toto
{
public:
titi(const toto& t) : toto(t) {}
void go() { cout << "ok" << b << endl; }
};
int main()
{
toto* toto1 = new toto();
titi(*toto1).go();
// ou bien
titi* titi1 = new titi(*toto1);
titi1->go();
return 0;
}
Le code suivant marche pas toujours, pouvez-vous me donner la bonne façon de le coder:
class toto { public: toto(); int b; void tata(); };
class titi: toto { public: void go(); };
void titi::go() { cout << "ok" << b << endl; }
int main(int argc, char *argv[]) { toto* toto1 = new toto(); titi *titi1 = (titi*) toto1; titi1->go(); return 0; }
PS: Je n'ai pas envie de rajouter une fonction virtuelle go() à toto (en fait, je ne le peux pas, toto étant une librairie à laquelle je n'ai pas accès).
Le problème est que ce code ne fonctionne que par hasard s'il a l'air de fonctionner. La norme du langage C++ dit que le comportement de ton programme est indéfini - cela veut dire tout simplement que le programme n'a pas de sens. C'est une pure perte de temps de vouloir savoir le *pourquoi*. C'est un programme contre le langage....
Une facon légale de faire marcher le programme est de créer "on the fly" un objet titi à partir de ton toto qui utilise pour sa construction un constructeur de copie toto(const toto&)
class titi: toto { public: titi(const toto& t) : toto(t) {} void go() { cout << "ok" << b << endl; } };
int main() { toto* toto1 = new toto(); titi(*toto1).go(); // ou bien titi* titi1 = new titi(*toto1); titi1->go(); return 0; }