OVH Cloud OVH Cloud

Pointeur de fonction et classes

1 réponse
Avatar
google
Bonjour,

je rencontre un problème en C++ que j'ai résolu en partie grâce à vos
contributions et Google...
Je m'explique :
j'ai des classes B, C, D qui héritent toutes d'une même classe A.
Dans la classe A, je définit un type pointeur sur fonction et j'ai une
structure en attribut de A du type :

typedef int(A::*ptrFunc)(void)
struct maStruct{
char * name;
ptrFunc fct;
};


class A{
public:
maStruct tableau[10];
}

Je vous épargne les détails, c'est juste pour donner l'idée
Ce que j'aimerais, c'est que dans B, C ou D, je puisse définir dans ce
tableau des méthodes appartenant à B, C ou D.
Enfin, pour être plus clair, que le tableau de B ne contienne que des
méthodes de B, que celui de C ne contienne que des méthodes de C, ...
Evidemment, à la compil, ça ne marche pas puisqu'il me dit que le type "B"
(ou C ou D) ne correspond pas à "A" dans le typedef du pointeur sur
fonction. Ca paraît relativement logique, mais je pensais qu'avec la notion
d'héritage, ça ne serait pas un problème.
La solution temporaire que j'ai trouvée et de définir des méthodes
virtuelles. Mais c'est pas très pratique et pas super beau. Avez vous une
solution sachant que, dans mes classes B, C et D, je remplit mon tableau de
la façon suivante :

tableau[0].name = "toto";
tableau[0].fct = &B::methodB;

(respectivement &C, &D).

Merci d'avance pour vos conseils !
--
lomba

1 réponse

Avatar
Vianney Lançon
Le 10 Dec 2003 23:52:43 -0800, dans fr.comp.lang.c++,
lomba a dit :
Bonjour,

je rencontre un problème en C++ que j'ai résolu en partie grâce à vos
contributions et Google...
Je m'explique :
j'ai des classes B, C, D qui héritent toutes d'une même classe A.
Dans la classe A, je définit un type pointeur sur fonction et j'ai une
structure en attribut de A du type :

typedef int(A::*ptrFunc)(void)
struct maStruct{
char * name;
ptrFunc fct;
};


class A{
public:
maStruct tableau[10];
}

Je vous épargne les détails, c'est juste pour donner l'idée
Ce que j'aimerais, c'est que dans B, C ou D, je puisse définir dans ce
tableau des méthodes appartenant à B, C ou D.
Enfin, pour être plus clair, que le tableau de B ne contienne que des
méthodes de B, que celui de C ne contienne que des méthodes de C, ...
Evidemment, à la compil, ça ne marche pas puisqu'il me dit que le type "B"
(ou C ou D) ne correspond pas à "A" dans le typedef du pointeur sur
fonction. Ca paraît relativement logique, mais je pensais qu'avec la notion
d'héritage, ça ne serait pas un problème.
La solution temporaire que j'ai trouvée et de définir des méthodes
virtuelles. Mais c'est pas très pratique et pas super beau. Avez vous une
solution sachant que, dans mes classes B, C et D, je remplit mon tableau de
la façon suivante :

tableau[0].name = "toto";
tableau[0].fct = &B::methodB;

(respectivement &C, &D).

Merci d'avance pour vos conseils !
--
lomba



class Properties
{
private:
typedef std::map < std::string, boost::function1<void> >
Container;

public:
void call(const std::string & propertyName)
{
Container::const_iterator it = m_propertymap.find(propertyName);
assert(it != m_propertyap.end());
it->second();
}
template <class T>
void add(const std::string & propertyName,
T* instance, void(T::*fun)())
{
assert(m_propertyMap.find(propertyName) == m_propertyMap.end());
m_propertyMap[propertyName] = std::bind_first(std::mem_fun(&fun), instance);
}

private:
Container m_propertyMap;
};


void test()
{
A a;
B b;
C c;

Properties properties;
properties.add("A::fun", &A::funA, &a);
properties.add("B::fun", &B::funB, &b);
properties.add("C::fun", &C::funC, &c);
properties.call("B::fun");
}

Si tu n'as pas le droit d'utiliser boost. Tu peux réimplémenter
functor1.

Tu fais une classe template FunctorHolder qui contient un T* instance et un
void (T::*fun)(). Tu définis l'operator() pour faire instance->fun().

Tu fait dériver cette classe d'une classe abstraite nommée
FunctorPlaceHolder déclarant l'operator() comme étant abstrait.

Ensuite tu utilise une enveloppe nommée Functor ayant un FunctorPlaceHolder
et qui, dans son constructeur template, cree un FunctorHolder et affecte
son FunctorPlaceHolder.

Ensuite avec ton Functor tu n'as plus qu'à définir ton operator() comme
functorPlaceHolder->operator().

Ensuite tu fait un copier coller, a chaque fois que tu veux augmenter
le nombre de paramètre. Si dans un 2ond temps du gère les types de
retour tu es obligé de faire une spécialisation partiel de template
si ton type de retour est "void".

--
Vianney LANÇON
radix omnia malorum prematurae optimisatia est
-- Donald Knuth