2 votes

passage d'une fonction comme paramètre de construction au constructeur de la classe de base lors de l'initialisation

#include <iostream>
#include<cstdio>
#include<typeinfo>

using std::cout;
using std::endl;

class foo;
class bar
{
    public:
        bar()
        {
        }
        bar(void (*getNextValue)(void)):memberFunctionPointer(getNextValue)
        {
        }
        void calltoderivedslass()
        {
            //  *memberFunctionPointer();
            ((bar*)this)->bar::memberFunctionPointer;
        }
        void (foo::*memberFunctionPointer)();
};

class foo : public bar
{
    public:
        foo( ):bar(static_cast<foo::*memberFunctionPointer>(&foo::hello))
        {
        }
        void hello()
        {
            printf("Hello \n\n");
        }
};
void byebye()
{
    cout << "bye" << endl;
}
int main()
{
    foo testfoo;
    //((testfoo).*(testfoo.memberFunctionPointer))();
    return 0;
}

Erreur :

classname.cpp: In constructor "bar::bar(void (*)())":
classname.cpp:15:68: error: cannot convert "void (*)()" to "void (foo::*)()" in initialization
classname.cpp: In constructor "foo::foo()":
classname.cpp:29:25: error: expected type-specifier
classname.cpp:29:25: error: expected ">"
classname.cpp:29:25: error: expected "("
classname.cpp:29:30: error: expected unqualified-id before "*" token
classname.cpp:31:2: error: expected "{" at end of input

Attentes :

Je veux initialiser le pointeur de la fonction de la classe de base pour l'initialiser à la fonction membre de la classe dérivée. Je veux l'initialiser lors de la création d'un objet de la classe dérivée. A partir de la classe de base, je veux appeler la fonction de la classe dérivée en utilisant le pointeur de fonction acquis.

Merci d'avance à tous.

2voto

wasthishelpful Points 10726

Il me semble qu'il s'agit de méthodes virtuelles :

class bar
{
    public:
        bar()
        {
        }
        void calltoderivedslass()
        {
            this->hello();
        }
        virtual void hello() = 0;
};

class foo : public bar
{
    public:
        foo( )
        {
        }
        void hello() override
        {
            printf("Hello \n\n");
        }
};

Une autre solution consiste à utiliser le modèle Curiously Recurring Template Pattern ( CRTP ) pour obtenir un polymorphisme statique :

template<typename T>
class bar
{
    public:
        bar()
        {
        }
        void calltoderivedslass()
        {
            static_cast<T*>(this)->hello();
        }
};

class foo : public bar<foo>
{
    public:
        foo( )
        {
        }
        void hello()
        {
            printf("Hello \n\n");
        }
};

Si vous souhaitez vraiment conserver des pointeurs vers les fonctions membres, vous pouvez envisager de recourir à std::function lié à this :

class bar
{
    public:
        bar()
        {
        }
        template<typename F>
        bar(F&& getNextValue):memberFunctionPointer(std::forward<F>(getNextValue))
        {
        }
        void calltoderivedslass()
        {
            this->memberFunctionPointer();
        }
        std::function<void()> memberFunctionPointer;
};

class foo : public bar
{
    public:
        foo( ):bar(std::bind(&foo::hello, this))
        {
        }
        void hello()
        {
            printf("Hello \n\n");
        }
};

Avec une utilisation prolongée, je suppose :

void byebye()
{
    cout << "bye" << endl;
}
int main()
{
    bar testbar(byebye);
    testbar.calltoderivedslass(); // not a derived class, but it works
    return 0;
}

0voto

Simon Kraemer Points 344

Votre constructeur pour bar est erronée.

Le constructeur bar(void (*getNextValue)(void)) n'attend pas un pointeur de fonction membre d'une fonction de foo et donc d'initialiser bar::memberFunctionPointer n'est pas possible avec le type de getNextValue .

Vous devez changer le paramètre dans le constructeur en void (foo::*getNextValue)(void) pour qu'il soit compilé.

Pourtant, la conception générale ne me semble pas vraiment correcte... Je pense donc que la réponse de @wasthishelpful est plus utile ;-)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X