Mais bien sûr ça ne fonctionne pas, j'ai les messages d'erreur suivants
(BCB6)
[C++ Erreur] _algo.h(65): E2034 Impossible de convertir 'ObjetBase *' en
'const ObjetThumb *'
[C++ Erreur] _algo.h(65): E2342 Mauvaise correspondance de type dans le
paramètre '__x' ('const ObjetThumb * const &' désiré, 'ObjetBase *'
obtenu)
Alors du coup je suis obligé de déclarer DrawThumb et DrawText virtuelles
dans ObjetBase, alors qu'elles ne sont utilisées respectivement que dans
ObjetThumb et ObjetText.
Y a-t-il moyen de faire autrement?
Sinon par rapport au même cas de figure, existe-il un pattern quelconque,
ou une méthode à suivre, pour m'assurer que les ObjetThumb sont bien
utilisés par ListeThumb et ObjetText par ListeText?
[Ici, un destructeur virtuel serait sans doute indiqué également]
};
class ListeThumb : public ListeBase { public: };
class ListeText : public ListeBase { public: };
Fabien LE LEZ
On 20 Jan 2006 03:41:19 GMT, Michael :
existe-il un pattern quelconque, ou une méthode à suivre, pour m'assurer que les ObjetThumb sont bien utilisés par ListeThumb et ObjetText par ListeText?
Tu veux dire, que aucun objet de classe ObjetThumb ne puisse être inséré dans un ListeText ?
Il faut vérifier, à chaque insertion (ou une fois pour toutes à la fin des insertions), que pour chaque pointeur p inséré, dynamic_cast<ObjetText*>(p) != 0.
Ne sachant comment tu remplis tes tableaux, je ne saurais t'en dire plus.
On 20 Jan 2006 03:41:19 GMT, Michael
<michael_delva.enlever@hotmail.com>:
existe-il un pattern quelconque,
ou une méthode à suivre, pour m'assurer que les ObjetThumb sont bien
utilisés par ListeThumb et ObjetText par ListeText?
Tu veux dire, que aucun objet de classe ObjetThumb ne puisse être
inséré dans un ListeText ?
Il faut vérifier, à chaque insertion (ou une fois pour toutes à la fin
des insertions), que pour chaque pointeur p inséré,
dynamic_cast<ObjetText*>(p) != 0.
Ne sachant comment tu remplis tes tableaux, je ne saurais t'en dire
plus.
existe-il un pattern quelconque, ou une méthode à suivre, pour m'assurer que les ObjetThumb sont bien utilisés par ListeThumb et ObjetText par ListeText?
Tu veux dire, que aucun objet de classe ObjetThumb ne puisse être inséré dans un ListeText ?
Il faut vérifier, à chaque insertion (ou une fois pour toutes à la fin des insertions), que pour chaque pointeur p inséré, dynamic_cast<ObjetText*>(p) != 0.
Ne sachant comment tu remplis tes tableaux, je ne saurais t'en dire plus.
Michael
J'ai l'impression que tu te compliques inutilement la vie. Voici ce que je propose :
J'ai effectivement choisi un exemple pas trop clair, je n'aurais pas du préfixer les 2 fonctions avec Draw. Et en plus je n'ai pas de fonction équivalente dans la classe ObjetText. Il était trop tard (tôt?) quand j'ai posté :(
class ObjetBase { ObjetBase() {} };
class ObjetThumb : public ObjetBase { ObjetThumb() : ObjetBase() {}
void DrawPreview() { } };
class ObjetText : public ObjetBase { ObjetText() : ObjetBase() {} };
class ListeBase { protected: std::vector<ObjetBase*> liste; };
class ListeThumb : public ListeBase { public: void foo() { std::for_each(liste.begin(),liste.end(),std::mem_fun (&ObjetThumb::DrawPreview)); } };
Voilà, c'est mieux comme ça. Donc du coup la question se repose: Y a-t-il une manière de faire qui m'évite de déclarer DrawPreview en virtual dans ObjetBase?
J'ai l'impression que tu te compliques inutilement la vie. Voici ce
que je propose :
J'ai effectivement choisi un exemple pas trop clair, je n'aurais pas du
préfixer les 2 fonctions avec Draw. Et en plus je n'ai pas de fonction
équivalente dans la classe ObjetText. Il était trop tard (tôt?) quand
j'ai posté :(
class ObjetBase
{
ObjetBase() {}
};
class ObjetThumb : public ObjetBase
{
ObjetThumb() : ObjetBase() {}
void DrawPreview() { }
};
class ObjetText : public ObjetBase
{
ObjetText() : ObjetBase() {}
};
class ListeBase
{
protected:
std::vector<ObjetBase*> liste;
};
class ListeThumb : public ListeBase
{
public:
void foo()
{
std::for_each(liste.begin(),liste.end(),std::mem_fun
(&ObjetThumb::DrawPreview));
}
};
Voilà, c'est mieux comme ça. Donc du coup la question se repose:
Y a-t-il une manière de faire qui m'évite de déclarer DrawPreview en
virtual dans ObjetBase?
J'ai l'impression que tu te compliques inutilement la vie. Voici ce que je propose :
J'ai effectivement choisi un exemple pas trop clair, je n'aurais pas du préfixer les 2 fonctions avec Draw. Et en plus je n'ai pas de fonction équivalente dans la classe ObjetText. Il était trop tard (tôt?) quand j'ai posté :(
class ObjetBase { ObjetBase() {} };
class ObjetThumb : public ObjetBase { ObjetThumb() : ObjetBase() {}
void DrawPreview() { } };
class ObjetText : public ObjetBase { ObjetText() : ObjetBase() {} };
class ListeBase { protected: std::vector<ObjetBase*> liste; };
class ListeThumb : public ListeBase { public: void foo() { std::for_each(liste.begin(),liste.end(),std::mem_fun (&ObjetThumb::DrawPreview)); } };
Voilà, c'est mieux comme ça. Donc du coup la question se repose: Y a-t-il une manière de faire qui m'évite de déclarer DrawPreview en virtual dans ObjetBase?
Michael
Tu veux dire, que aucun objet de classe ObjetThumb ne puisse être inséré dans un ListeText ?
Il faut vérifier, à chaque insertion (ou une fois pour toutes à la fin des insertions), que pour chaque pointeur p inséré, dynamic_cast<ObjetText*>(p) != 0.
Ne sachant comment tu remplis tes tableaux, je ne saurais t'en dire plus.
class ListeObjetsThumb : public ListeObjetsBase { public: void CreateObject() { ObjetThumb * objet = new ObjetThumb(); AddObject(objet); //Gestion de la représentation sous forme graphique de l'objet } };
class ListeObjetsText : public ListeObjetsBase { public: void CreateObject() { ObjetText * objet = new ObjetText(); AddObject(objet); //Gestion de la représentation sous forme texte de l'objet } };
Tu veux dire, que aucun objet de classe ObjetThumb ne puisse être
inséré dans un ListeText ?
Il faut vérifier, à chaque insertion (ou une fois pour toutes à la fin
des insertions), que pour chaque pointeur p inséré,
dynamic_cast<ObjetText*>(p) != 0.
Ne sachant comment tu remplis tes tableaux, je ne saurais t'en dire
plus.
class ListeObjetsThumb : public ListeObjetsBase
{
public:
void CreateObject()
{
ObjetThumb * objet = new ObjetThumb();
AddObject(objet);
//Gestion de la représentation sous forme graphique de l'objet
}
};
class ListeObjetsText : public ListeObjetsBase
{
public:
void CreateObject()
{
ObjetText * objet = new ObjetText();
AddObject(objet);
//Gestion de la représentation sous forme texte de l'objet
}
};
Tu veux dire, que aucun objet de classe ObjetThumb ne puisse être inséré dans un ListeText ?
Il faut vérifier, à chaque insertion (ou une fois pour toutes à la fin des insertions), que pour chaque pointeur p inséré, dynamic_cast<ObjetText*>(p) != 0.
Ne sachant comment tu remplis tes tableaux, je ne saurais t'en dire plus.
class ListeObjetsThumb : public ListeObjetsBase { public: void CreateObject() { ObjetThumb * objet = new ObjetThumb(); AddObject(objet); //Gestion de la représentation sous forme graphique de l'objet } };
class ListeObjetsText : public ListeObjetsBase { public: void CreateObject() { ObjetText * objet = new ObjetText(); AddObject(objet); //Gestion de la représentation sous forme texte de l'objet } };
Cyrille
J'ai l'impression que tu te compliques inutilement la vie. Voici ce que je propose :
J'ai effectivement choisi un exemple pas trop clair, je n'aurais pas du préfixer les 2 fonctions avec Draw. Et en plus je n'ai pas de fonction équivalente dans la classe ObjetText. Il était trop tard (tôt?) quand j'ai posté :(
class ObjetBase { ObjetBase() {} };
class ObjetThumb : public ObjetBase { ObjetThumb() : ObjetBase() {}
void DrawPreview() { } };
class ObjetText : public ObjetBase { ObjetText() : ObjetBase() {} };
class ListeBase { protected: std::vector<ObjetBase*> liste; };
class ListeThumb : public ListeBase { public: void foo() { std::for_each(liste.begin(),liste.end(),std::mem_fun (&ObjetThumb::DrawPreview)); } };
Voilà, c'est mieux comme ça. Donc du coup la question se repose: Y a-t-il une manière de faire qui m'évite de déclarer DrawPreview en virtual dans ObjetBase?
Tu voudrais, si j'ai bien compris, que ton for_each appelle le DrawPreview de ObjetThumb quand bien même il n'a que des pointeurs sur ObjetBase à sa disposition. A première vue, je me demanderais: "mais pourquoi est-ce que ListeThumb ne contient pas simplement un std::vector<ObjetThumb*>" ? Un ListeThumb est-il susceptible de contenir autre chose que des ObjetThumb? Si ce n'est pas le cas, il y a une erreur de conception à vouloir utiliser un vecteur d'ObjetBase à l'intérieur, à mon sens.
Si vraiment tu veux faire ça, tu peux t'en sortir avec une fonction libre:
void DrawPreviewImpl(ObjetBase * obj) { try { ObjetThumb * thumb = dynamic_cast<ObjetThumb *>( obj ); thumb->DrawPreview(); } catch (std::bad_cast) { // ne devrait pas arriver là } }
et ainsi utiliser for_each ainsi: std::for_each(liste.begin(), liste.end(), DrawPreviewImpl);
Aussi, pour faire un dynamic_cast sur un pointeur d'ObjetBase, il faut que ce soit une classe polymorphe, c'est-à-dire qu'elle contient au moins une fonction virtuelle. Comme de toute façons il faudrait que tu mettes aussi un destructeur virtuel dans cette classe, celui-ci suffit.
J'ai l'impression que tu te compliques inutilement la vie. Voici ce
que je propose :
J'ai effectivement choisi un exemple pas trop clair, je n'aurais pas du
préfixer les 2 fonctions avec Draw. Et en plus je n'ai pas de fonction
équivalente dans la classe ObjetText. Il était trop tard (tôt?) quand
j'ai posté :(
class ObjetBase
{
ObjetBase() {}
};
class ObjetThumb : public ObjetBase
{
ObjetThumb() : ObjetBase() {}
void DrawPreview() { }
};
class ObjetText : public ObjetBase
{
ObjetText() : ObjetBase() {}
};
class ListeBase
{
protected:
std::vector<ObjetBase*> liste;
};
class ListeThumb : public ListeBase
{
public:
void foo()
{
std::for_each(liste.begin(),liste.end(),std::mem_fun
(&ObjetThumb::DrawPreview));
}
};
Voilà, c'est mieux comme ça. Donc du coup la question se repose:
Y a-t-il une manière de faire qui m'évite de déclarer DrawPreview en
virtual dans ObjetBase?
Tu voudrais, si j'ai bien compris, que ton for_each appelle le
DrawPreview de ObjetThumb quand bien même il n'a que des pointeurs sur
ObjetBase à sa disposition.
A première vue, je me demanderais: "mais pourquoi est-ce que ListeThumb
ne contient pas simplement un std::vector<ObjetThumb*>" ? Un ListeThumb
est-il susceptible de contenir autre chose que des ObjetThumb? Si ce
n'est pas le cas, il y a une erreur de conception à vouloir utiliser un
vecteur d'ObjetBase à l'intérieur, à mon sens.
Si vraiment tu veux faire ça, tu peux t'en sortir avec une fonction libre:
void DrawPreviewImpl(ObjetBase * obj)
{
try
{
ObjetThumb * thumb = dynamic_cast<ObjetThumb *>( obj );
thumb->DrawPreview();
}
catch (std::bad_cast)
{
// ne devrait pas arriver là
}
}
et ainsi utiliser for_each ainsi:
std::for_each(liste.begin(), liste.end(), DrawPreviewImpl);
Aussi, pour faire un dynamic_cast sur un pointeur d'ObjetBase, il faut
que ce soit une classe polymorphe, c'est-à-dire qu'elle contient au
moins une fonction virtuelle. Comme de toute façons il faudrait que tu
mettes aussi un destructeur virtuel dans cette classe, celui-ci suffit.
J'ai l'impression que tu te compliques inutilement la vie. Voici ce que je propose :
J'ai effectivement choisi un exemple pas trop clair, je n'aurais pas du préfixer les 2 fonctions avec Draw. Et en plus je n'ai pas de fonction équivalente dans la classe ObjetText. Il était trop tard (tôt?) quand j'ai posté :(
class ObjetBase { ObjetBase() {} };
class ObjetThumb : public ObjetBase { ObjetThumb() : ObjetBase() {}
void DrawPreview() { } };
class ObjetText : public ObjetBase { ObjetText() : ObjetBase() {} };
class ListeBase { protected: std::vector<ObjetBase*> liste; };
class ListeThumb : public ListeBase { public: void foo() { std::for_each(liste.begin(),liste.end(),std::mem_fun (&ObjetThumb::DrawPreview)); } };
Voilà, c'est mieux comme ça. Donc du coup la question se repose: Y a-t-il une manière de faire qui m'évite de déclarer DrawPreview en virtual dans ObjetBase?
Tu voudrais, si j'ai bien compris, que ton for_each appelle le DrawPreview de ObjetThumb quand bien même il n'a que des pointeurs sur ObjetBase à sa disposition. A première vue, je me demanderais: "mais pourquoi est-ce que ListeThumb ne contient pas simplement un std::vector<ObjetThumb*>" ? Un ListeThumb est-il susceptible de contenir autre chose que des ObjetThumb? Si ce n'est pas le cas, il y a une erreur de conception à vouloir utiliser un vecteur d'ObjetBase à l'intérieur, à mon sens.
Si vraiment tu veux faire ça, tu peux t'en sortir avec une fonction libre:
void DrawPreviewImpl(ObjetBase * obj) { try { ObjetThumb * thumb = dynamic_cast<ObjetThumb *>( obj ); thumb->DrawPreview(); } catch (std::bad_cast) { // ne devrait pas arriver là } }
et ainsi utiliser for_each ainsi: std::for_each(liste.begin(), liste.end(), DrawPreviewImpl);
Aussi, pour faire un dynamic_cast sur un pointeur d'ObjetBase, il faut que ce soit une classe polymorphe, c'est-à-dire qu'elle contient au moins une fonction virtuelle. Comme de toute façons il faudrait que tu mettes aussi un destructeur virtuel dans cette classe, celui-ci suffit.
Tu voudrais, si j'ai bien compris, que ton for_each appelle le DrawPreview de ObjetThumb quand bien même il n'a que des pointeurs sur ObjetBase à sa disposition. A première vue, je me demanderais: "mais pourquoi est-ce que ListeThumb ne contient pas simplement un std::vector<ObjetThumb*>" ? Un ListeThumb est-il susceptible de contenir autre chose que des ObjetThumb? Si ce n'est pas le cas, il y a une erreur de conception à vouloir utiliser un vecteur d'ObjetBase à l'intérieur, à mon sens.
Parce que j'ai aussi une classe ListeText qui s'appuie sur std::vector <ObjetBase*>.
En fait, ListeBase propose les implémentations concernant la gestion de cette liste. ListeThumb et ListeText déterminent simplement la manière dont seront affichés les Objet.
Par exemple, pour la copie d'un objet:
void ListeBase::CopyObject(const int objectId, const int newId) { //On récupère l'objet ObjetBase * object = GetObjectFromIndex(objectId);
//On le copie ObjetBase * pastedObject = new ObjetBase(object);
void ListeThumb::CopyObject(const int idObject, const int newId) { //Copie de l'objet dans le vecteur ListeBase::CopyObject(idObject,newId);
//Représentation graphique du copier (Affichage d'une icône sur l'image de prévisualisation de l'objet par exemple) //... }
void ListeText::CopyObject(const int idObject, const int newId) { //Copie de l'objet dans le vecteur ListeBase::CopyObject(idObject,newId);
//Représentation texte du copier //... }
Si vraiment tu veux faire ça, tu peux t'en sortir avec une fonction libre:
void DrawPreviewImpl(ObjetBase * obj) { try { ObjetThumb * thumb = dynamic_cast<ObjetThumb *>( obj ); thumb->DrawPreview(); } catch (std::bad_cast) { // ne devrait pas arriver là } }
et ainsi utiliser for_each ainsi: std::for_each(liste.begin(), liste.end(), DrawPreviewImpl);
Aussi, pour faire un dynamic_cast sur un pointeur d'ObjetBase, il faut que ce soit une classe polymorphe, c'est-à-dire qu'elle contient au moins une fonction virtuelle. Comme de toute façons il faudrait que tu mettes aussi un destructeur virtuel dans cette classe, celui-ci suffit.
Tu voudrais, si j'ai bien compris, que ton for_each appelle le
DrawPreview de ObjetThumb quand bien même il n'a que des pointeurs sur
ObjetBase à sa disposition.
A première vue, je me demanderais: "mais pourquoi est-ce que
ListeThumb ne contient pas simplement un std::vector<ObjetThumb*>" ?
Un ListeThumb est-il susceptible de contenir autre chose que des
ObjetThumb? Si ce n'est pas le cas, il y a une erreur de conception à
vouloir utiliser un vecteur d'ObjetBase à l'intérieur, à mon sens.
Parce que j'ai aussi une classe ListeText qui s'appuie sur std::vector
<ObjetBase*>.
En fait, ListeBase propose les implémentations concernant la gestion de
cette liste. ListeThumb et ListeText déterminent simplement la manière
dont seront affichés les Objet.
Par exemple, pour la copie d'un objet:
void ListeBase::CopyObject(const int objectId, const int newId)
{
//On récupère l'objet
ObjetBase * object = GetObjectFromIndex(objectId);
//On le copie
ObjetBase * pastedObject = new ObjetBase(object);
void ListeThumb::CopyObject(const int idObject, const int newId)
{
//Copie de l'objet dans le vecteur
ListeBase::CopyObject(idObject,newId);
//Représentation graphique du copier (Affichage d'une icône sur l'image
de prévisualisation de l'objet par exemple)
//...
}
void ListeText::CopyObject(const int idObject, const int newId)
{
//Copie de l'objet dans le vecteur
ListeBase::CopyObject(idObject,newId);
//Représentation texte du copier
//...
}
Si vraiment tu veux faire ça, tu peux t'en sortir avec une fonction
libre:
void DrawPreviewImpl(ObjetBase * obj)
{
try
{
ObjetThumb * thumb = dynamic_cast<ObjetThumb *>( obj );
thumb->DrawPreview();
}
catch (std::bad_cast)
{
// ne devrait pas arriver là
}
}
et ainsi utiliser for_each ainsi:
std::for_each(liste.begin(), liste.end(), DrawPreviewImpl);
Aussi, pour faire un dynamic_cast sur un pointeur d'ObjetBase, il faut
que ce soit une classe polymorphe, c'est-à-dire qu'elle contient au
moins une fonction virtuelle. Comme de toute façons il faudrait que tu
mettes aussi un destructeur virtuel dans cette classe, celui-ci
suffit.
Tu voudrais, si j'ai bien compris, que ton for_each appelle le DrawPreview de ObjetThumb quand bien même il n'a que des pointeurs sur ObjetBase à sa disposition. A première vue, je me demanderais: "mais pourquoi est-ce que ListeThumb ne contient pas simplement un std::vector<ObjetThumb*>" ? Un ListeThumb est-il susceptible de contenir autre chose que des ObjetThumb? Si ce n'est pas le cas, il y a une erreur de conception à vouloir utiliser un vecteur d'ObjetBase à l'intérieur, à mon sens.
Parce que j'ai aussi une classe ListeText qui s'appuie sur std::vector <ObjetBase*>.
En fait, ListeBase propose les implémentations concernant la gestion de cette liste. ListeThumb et ListeText déterminent simplement la manière dont seront affichés les Objet.
Par exemple, pour la copie d'un objet:
void ListeBase::CopyObject(const int objectId, const int newId) { //On récupère l'objet ObjetBase * object = GetObjectFromIndex(objectId);
//On le copie ObjetBase * pastedObject = new ObjetBase(object);
void ListeThumb::CopyObject(const int idObject, const int newId) { //Copie de l'objet dans le vecteur ListeBase::CopyObject(idObject,newId);
//Représentation graphique du copier (Affichage d'une icône sur l'image de prévisualisation de l'objet par exemple) //... }
void ListeText::CopyObject(const int idObject, const int newId) { //Copie de l'objet dans le vecteur ListeBase::CopyObject(idObject,newId);
//Représentation texte du copier //... }
Si vraiment tu veux faire ça, tu peux t'en sortir avec une fonction libre:
void DrawPreviewImpl(ObjetBase * obj) { try { ObjetThumb * thumb = dynamic_cast<ObjetThumb *>( obj ); thumb->DrawPreview(); } catch (std::bad_cast) { // ne devrait pas arriver là } }
et ainsi utiliser for_each ainsi: std::for_each(liste.begin(), liste.end(), DrawPreviewImpl);
Aussi, pour faire un dynamic_cast sur un pointeur d'ObjetBase, il faut que ce soit une classe polymorphe, c'est-à-dire qu'elle contient au moins une fonction virtuelle. Comme de toute façons il faudrait que tu mettes aussi un destructeur virtuel dans cette classe, celui-ci suffit.
Fabien LE LEZ
On Fri, 20 Jan 2006 13:46:31 +0100, Cyrille :
try { ObjetThumb * thumb = dynamic_cast<ObjetThumb *>( obj );
dynamic_cast<> sur un pointeur ne lance pas d'exception. Il renvoie éventuellement un pointeur nul.
On Fri, 20 Jan 2006 13:46:31 +0100, Cyrille <cyrille@frsf.invalid>:
try
{
ObjetThumb * thumb = dynamic_cast<ObjetThumb *>( obj );
dynamic_cast<> sur un pointeur ne lance pas d'exception. Il renvoie
éventuellement un pointeur nul.