visual c++void*为函数提供参数

visual c++ void* to parameter to a function

本文关键字:参数 函数 c++void visual      更新时间:2023-10-16

我在一些库中有这个函数:

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无法从'void(__thiscall)转换参数2myApp::*)(const std::vector<_Ty>&)'到'void*'

我该如何解决这个问题?

提前感谢!

您无法解决此问题。不能可靠地将函数指针强制转换为void *并返回。

(我建议您重新设计程序并避开void*;在C++中并没有真正的必要。)

这里的问题是,您试图将类方法作为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)。

您应该避免使用void*,尤其是在尝试使用函数指针时。我假设您只关注myApp类中的成员函数指针,并且只对以const std::vector<std::string> &args为参数的成员函数指示器感兴趣。这个typedef将创建适当的类型,并将其称为MemFunType

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

这里有一个完整的例子(在ideone上),其中有两个不同的成员函数你可能感兴趣,TestFnTestFnBackwards。这个例子可能不是很有用,但它给出了一些成员函数指针的例子。

#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 );
}