OVH Cloud OVH Cloud

Récupération du type d'un élément d'une liste

4 réponses
Avatar
Ygster
Salut à tous,

J'ai une hiérarchie de classe, dont la classe de base est Objet et Bouton
et Fenetre sont 2 classes dérivées.

Je dois faire une liste d'éléments et pour cela j'ai choisi de faire une
liste d'Objets pour pouvoir y stocker indifféremment des Boutons ou des
Fenetres.

Le problème est que ensuite je dois parcourir la liste pour effectuer un
traitement en fonction du type de l'objet. Mais en utilisant
typeid(*ptr).name() il me donne Objet. C'est assez logique puisque j'ai
fait une liste d'Objet, mais je me demande si il est possible de retrouver
le type initial de l'objet ?

En fait plus généralement est-ce qu'il y a un transformation du type
initial vers le type Objet dans ce cas ?

Merci d'avance.
A+
Ygster

4 réponses

Avatar
Benoit Rousseau
Ygster wrote:
Salut à tous,

J'ai une hiérarchie de classe, dont la classe de base est Objet et Bouton
et Fenetre sont 2 classes dérivées.

Je dois faire une liste d'éléments et pour cela j'ai choisi de faire une
liste d'Objets pour pouvoir y stocker indifféremment des Boutons ou des
Fenetres.

Le problème est que ensuite je dois parcourir la liste pour effectuer un
traitement en fonction du type de l'objet. Mais en utilisant
typeid(*ptr).name() il me donne Objet. C'est assez logique puisque j'ai
fait une liste d'Objet, mais je me demande si il est possible de retrouver
le type initial de l'objet ?


Est ce que ton objet contient une fonction virtuelle ? Si ce n'est pas
le cas, la hierarchie n'est pas polymorphe. Le mieux est de déclarer le
destructeur virtuel (puisqu'il doit l'être pour détruire les objets de
Bouton ou Fenetre) :
class Objet {
public:
virtual ~Object() = 0; // =0 ou {}
};

Voila, tu peux utiliser typeid maintenant :)


--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

Avatar
Loïc Joly
Ygster wrote:

Salut à tous,

J'ai une hiérarchie de classe, dont la classe de base est Objet et Bouton
et Fenetre sont 2 classes dérivées.

Je dois faire une liste d'éléments et pour cela j'ai choisi de faire une
liste d'Objets pour pouvoir y stocker indifféremment des Boutons ou des
Fenetres.


Une liste d'Objets ne peut stocker que des Objets. Pour avoir du
polymorphisme, il faut une liste de pointeurs sur des Objets (ou des
pointeurs intelligents pour ne pas devoir gérer la mémoire à la main).

Le problème est que ensuite je dois parcourir la liste pour effectuer un
traitement en fonction du type de l'objet.


C'est le rôle d'une fonction virtuele, qui est un mécanisme plus souple
que de déterminier le type réel de l'objet puis agir en fonction.

Mais en utilisant
typeid(*ptr).name() il me donne Objet.


AMA, le typeid().name() ne peut servir que pour du debug. Rien n'assure
qu'il est utile. Le typeid() lui même est je pense rarement utilisé. On
a en effet tendance en général à vouloir savoir si un objet est d'une
classe ou d'une de ses classes dérivées que de savoir simplement s'il
est d'une classe. La chose à utiliser dans ce cas et dynamic_cast.



--
Loïc

Avatar
Vincent Richard

J'ai une hiérarchie de classe, dont la classe de base est Objet et Bouton
et Fenetre sont 2 classes dérivées.

Je dois faire une liste d'éléments et pour cela j'ai choisi de faire une
liste d'Objets pour pouvoir y stocker indifféremment des Boutons ou des
Fenetres.

Le problème est que ensuite je dois parcourir la liste pour effectuer un
traitement en fonction du type de l'objet. Mais en utilisant
typeid(*ptr).name() il me donne Objet. C'est assez logique puisque j'ai
fait une liste d'Objet


Non, avec typeid(*ptr), il devrait renvoyer le type _dynamique_ de l'objet
pointé, ce qui n'est pas le cas avec typeid(ptr) (type statique).

mais je me demande si il est possible de retrouver le type initial
de l'objet ?


Petit test :

#include <list>
#include <iostream>
#include <typeinfo>

class Objet { public: virtual ~Objet() {} };
class Bouton : public Objet { };
class Fenetre : public Objet { };

int main()
{
std::list <Objet*> lis;

lis.push_back(new Bouton);
lis.push_back(new Fenetre);

std::cout << typeid(lis.back()).name() << std::endl;
std::cout << typeid(*lis.back()).name() << std::endl;
}

Renvoie bien (g++ 3.2.2) :

P5Objet == Objet*
7Fenetre == Fenetre

Evidemment, il faut au moins une fonction virtuelle dans la classe de base
(ici destructeur virtuel de "Objet") pour que ça fonctionne.

Si tu veux tester le type des objets, ne compare pas la valeur renvoyée
directement avec une chaîne de caractères (pas portable), mais compare
la avec un autre typeid() :

if (typeid(*ptr) == typeid(Fenetre))
; // ...

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/

Avatar
Ygster
Le Mon, 01 Dec 2003 23:46:11 +0100, Vincent Richard a écrit :

Salut à tous,

Petit test :

#include <list>
#include <iostream>
#include <typeinfo>

class Objet { public: virtual ~Objet() {} };
class Bouton : public Objet { };
class Fenetre : public Objet { };

int main()
{
std::list <Objet*> lis;

lis.push_back(new Bouton);
lis.push_back(new Fenetre);

std::cout << typeid(lis.back()).name() << std::endl;
std::cout << typeid(*lis.back()).name() << std::endl;
}

Renvoie bien (g++ 3.2.2) :

P5Objet == Objet*
7Fenetre == Fenetre


Merci à tous les 3 pour vos réponses.
Effectivement, je n'avais pas mis de méthode virtuelle dans Objet donc
pas de polymorphisme. En plus comme j'utilise un iterator, il me faut un
niveau de plus pour retrouver le type initial (typeid(**ptr).name() ).

Merci encore.
A+
Ygster