c ++ void * для параметра в функцию - PullRequest
2 голосов
/ 05 января 2012

У меня есть эта функция в некоторой библиотеке:

class myConsole
{
    void addCommand( std::string command, void* fn );
    ...
}

и в моем классе у меня есть эта функция:

void myApp::TestFn( const std::vector<std::string> & args )
{
    // do something
}

в том же классе я называю это:

void myApp::initApp( )
{
    myConsole::getSingleton( ).addCommand( "FirstTest", &myApp::TestFn );
}

но это дает мне эту ошибку:

ошибка c2664 не может преобразовать параметр 2 из 'void (__ thiscall myApp :: *) (const std :: vector <_Ty> &) 'в' void * '

как я могу решить это?

спасибо заранее!

Ответы [ 3 ]

9 голосов
/ 05 января 2012

Вы не можете решить эту проблему.Вы не можете надежно привести указатель функции к void * и обратно.

(я советую вам перепроектировать программу и держаться подальше от void*; в C ++ это не нужно).

1 голос
/ 05 января 2012

Вам следует избегать void*, особенно при попытке использовать указатели функций. Я предполагаю, что вы смотрите только на указатели на функции-члены в классе myApp, и что вас интересуют только указатели на функции-члены, которые принимают const std::vector<std::string> &args в качестве аргумента. Этот typedef создаст соответствующий тип и назовет его MemFunType

typedef void (myApp :: * MemFunType) (const std::vector<std::string> &);

Вот полный пример (на ideone ), где вам могут быть интересны две различные функции-члена, TestFn и TestFnBackwards. Этот пример, вероятно, не очень полезен, но он дает несколько примеров указателей на функции-члены.

#include<iostream>
#include<vector>
using namespace std;

struct myApp;

struct myConsole
{
        typedef void (myApp :: * MemFunType) (const std::vector<std::string> &);
            void addCommand( std::string command, MemFunType fn );
};

struct myApp {
        void TestFn( const std::vector<std::string> & args ) {
                cout << " TestFn" << endl;
                for(std :: vector<std::string> :: const_iterator i = args.begin(); i!=args.end(); i++) {
                        cout << *i << endl;
                }
        }
        void TestFnBackwards( const std::vector<std::string> & args ) {
                cout << " TestFnBackwards" << endl;
                for(std :: vector<std::string> :: const_reverse_iterator i = args.rbegin(); i!=args.rend(); i++) {
                        cout << *i << endl;
                }
        }
        static myApp & getSingleton();
} ma;
myApp& myApp :: getSingleton() {
        return ma;
}

void myConsole :: addCommand( std::string , MemFunType fn ) {
        vector<string> words;
        words.push_back("hello");
        words.push_back("world");
        myApp &ma = myApp :: getSingleton();
        (ma.*fn)(words); // execute the member on the singleton object, using the words as the argument.
}

int main() {
        myConsole m;
        m.addCommand( "FirstTest", &myApp::TestFn );
        m.addCommand( "FirstTest", &myApp::TestFnBackwards );
}
1 голос
/ 05 января 2012

Проблема в том, что вы пытаетесь передать метод класса, как бы указатель void *.Это невозможно сделать.

Правильный способ сделать это - использовать шаблоны для метода void addCommand (std::string, void *).Что-то вроде

class myConsole {
    template <typename T>
    void addCommand( std::string command, T f);
};

struct Callback {
    myApp &app;
    Callback (myApp &a) : app(a) {
    }
    void operator() (const std::vector<std::string> &args) {
        app.TestFn(args);
    }
};

void myApp::initApp( )
{
    myConsole::getSingleton( ).addCommand( "FirstTest", Callback(*this) );
}

Это дает вам принцип обратного вызова в C ++, но я думаю, что вам нужно нечто более гибкое, чем это решение, поскольку вы на самом деле хотите автоматически выбирать команду, которая будет выполняться обратным вызовомэто дело TestFn).

...