OVH Cloud OVH Cloud

Polymorphisme et template

1 réponse
Avatar
Frédéric Mayot
Bonjour,

Voilà un petit bout de code qui compile mais qui plante à l'édition des
liens :

-------------------------------------------------------------
#include <iostream>

template <class T>
struct conteneur
{
T t;
T& get_value(){return t;}
};

struct base
{
virtual ~base(){}
virtual int f();
};

struct derive1 : public base
{
int f(){return 1;}
};

struct derive2 : public base
{
int f(){return 2;}
};

int main (int c, char** d)
{
conteneur<derive1> c1;
conteneur<derive2> c2;

conteneur<derive1>* p_c1 = &c1;
conteneur<derive2>* p_c2 = &c2;

conteneur<base>* p_b1 = reinterpret_cast<conteneur<base>*>(p_c1);
conteneur<base>* p_b2 = reinterpret_cast<conteneur<base>*>(p_c2);

std::cout << p_b1->get_value().f() << std::endl;
std::cout << p_b2->get_value().f() << std::endl;

return 1;
}

-------------------------------------------------------------

En gros, j'obtiens des pointeurs sur des instances de "conteneur" mais
dont je ne connais pas le paramètre du template. Par contre, je sais que
le paramètre est toujours une classe dérivée de "base".

Vous voyez ce qui cloche ?

Merci.

Fred

1 réponse

Avatar
Mathieu Roger
Bonjour,

Voilà un petit bout de code qui compile mais qui plante à l'édition des
liens :

-------------------------------------------------------------
#include <iostream>

template <class T>
struct conteneur
{
T t;
T& get_value(){return t;}
};

struct base
{
virtual ~base(){}
virtual int f();
};

struct derive1 : public base
{
int f(){return 1;}
};

struct derive2 : public base
{
int f(){return 2;}
};

int main (int c, char** d)
{
conteneur<derive1> c1;
conteneur<derive2> c2;

conteneur<derive1>* p_c1 = &c1;
conteneur<derive2>* p_c2 = &c2;

conteneur<base>* p_b1 = reinterpret_cast<conteneur<base>*>(p_c1);
conteneur<base>* p_b2 = reinterpret_cast<conteneur<base>*>(p_c2);

std::cout << p_b1->get_value().f() << std::endl;
std::cout << p_b2->get_value().f() << std::endl;

return 1;
}

-------------------------------------------------------------

En gros, j'obtiens des pointeurs sur des instances de "conteneur" mais
dont je ne connais pas le paramètre du template. Par contre, je sais que
le paramètre est toujours une classe dérivée de "base".

Vous voyez ce qui cloche ?



Dans conteneur<T> vous ne pouvez manipuler T en tant que valeur, vous
devez utiliser soit une référence (T&) soit un poiteur (T*)


conteneur<base>* p_b1 = reinterpret_cast<conteneur<base>*>(p_c1);


vous avez, il me semble converti c1 en un conteneur<base> et donc :

conteneur<base> =
struct conteneur
{
base t;
base& get_value()
{return t;}
};


et dans ce cas l'attribut t dans un objet de conteneur<base> est une
conversion vers base mais ne peut jamais être un objet ni de derive1 ni
de derive2
le problème d'édition de lien se trouve alors sur base::f() qui est
appelée sans qu'on ai fournit de corps

Ecrivez plutôt quelque chose comme :

template <class T>
struct conteneur
{
T* t;
T& get_value(){return *t;}
};

et

struct base
{
virtual ~base()
{}

// virtuel pur car on ne fournit pas de code
virtual int f() = 0 ;
};

C'est presque une règle de programmation : quand on manipule des objets
polymorphes, il faut le faire soit par pointeur soit par référence mais
jamais par valeur


Merci.

Fred