请教高手函数指针作为函数参数问题

时间:2021-01-18 18:47:41
RT


void F(函数指针)
{
//准备工作
prepare();

//执行
f1();//(或是f2(),f3()等)

//结束工作
endwork();
}

void f1(int a, int b)

void f2(flot a, flot b, flot c)

void f3(char * a, bool b)

void f3(class_a a)
...

main()
{//任务1
 F(f1(a, b));
 //任务2
 F(f2(a,b,c));
}

F的任务分成三步:准备、执行和结束。准备和结束对所有的任务都是相同的,执行部分则根据任务不同而不同。关键问题是不同任务对应的fi()的参数列表可能很不一样。这时候应该怎么实现呢?如果用模版实现也行。

我自己有一个不算办法的办法,就是在F里面搞一个struct_parameter结构体,所有功能函数fi()都搞成无参数,main中调用时先对结构体中的变量赋值,然后再F(fi())这么用。不过这会使得在main中的调用很罗嗦。原本一行搞定的,现在得多搞好些行给结构体赋值。

7 个解决方案

#1


将F写成一个宏:

#define F(fun) do{prepare(); fun; endwork();}while(0)

否则你
 F(f1(a, b));//这里的f1(a,b);是调用函数,而不是作为函数指针传递。

#2


tr1中的bind

例如VS2008 sp1


#include<functional>
using namespace std;
using namespace tr1;

void Func( function<void()> f)
{
//准备工作
//prepare();

f();
//结束工作
//endwork();
}

void f1(int a, int b);
void f2(float a, float b, float c);
void f3(char * a, bool b);

int main( int argc, char* argv[] )
{
Func( bind( f1 , 1,2) );
Func( bind( f2 , 1.0f,2.0f,3.0f) );
char* p = 0;
Func( bind( f3 , p,true) );
    return 0;
}


#3



void f1()
{
cout<<"Show()"<<endl;
}
void f2(int a, int b)
{
cout<<"a + b = "<<a + b<<endl;
}
void f3(char* ch)
{
cout<<ch<<endl;
}
typedef void (*Pf1)(void);
typedef void (*Pf2)(int a, int b);
typedef void (*Pf3)(char *ch);
union FunPtr
{
Pf1 fun1;
Pf2 fun2;
Pf3 fun3;
};
int main(int argc, char* argv[])
{
int a = 3;
int b = 4;
char* str = "Hello World!";

FunPtr fun;

fun.fun1 = (Pf1)f1;
fun.fun1();

fun.fun1 = (Pf1)f2;
fun.fun2(a, b);

fun.fun1 = (Pf1)f3;
fun.fun3(str);
system("pause");
return 0;
}


#4


F(fun_ptr)多个重载版本,也很烦。
可以讲参数抽象出来,比如

enum EArgType
{
    eTypeOne;
    eTypeTwo;
    // ...
};

struct ArgBase
{
    // ...
    EArgType _type; // 类型主要用来static_cast成对应的派生参数
};

struct ArgMore : public ArgBase
{
    // ...
};

typedef void (* PTR_FUN)( const ArgBase & arg );

void fun_a(const ArgBase & arg)
{
    ArgMore arg_more = static_cast<const ArgMore&>(arg);
    arg_more;
    // ... 
}

void Fun( PTR_FUN fun, const ArgBase & arg )
{
    // step one
    // ...

    // step two
    fun(arg);

    // ...
}

int main()
{
    ArgMore arg;
    // 填充arg
    Fun(fun_a, arg);

    // ...

    return 0;
}

#5


引用 2 楼 akirya 的回复:
tr1中的bind

例如VS2008 sp1
C/C++ code


#include<functional>
using namespace std;
using namespace tr1;

void Func( function<void()> f)
{
    //准备工作
    //prepare();

    f();
    //结束工作
    //endwor……


这个最好了

#6


请参考:
函数指针的几种用法 中“函数指针作为参数”的那部分。

#7


多谢各位,不好意思,一段时间断网了。手机只能看贴,登陆不上。

1楼好像没看懂问题
2楼的确实是好方法,但不幸我用的是vc2005...泪奔
3楼的没有解决根本问题
4楼的方法和我说的那个“不算办法的办法”本质上一样

我的问题已经解决,用va_list解决的,就是类似于printf传参的那种办法。

#1


将F写成一个宏:

#define F(fun) do{prepare(); fun; endwork();}while(0)

否则你
 F(f1(a, b));//这里的f1(a,b);是调用函数,而不是作为函数指针传递。

#2


tr1中的bind

例如VS2008 sp1


#include<functional>
using namespace std;
using namespace tr1;

void Func( function<void()> f)
{
//准备工作
//prepare();

f();
//结束工作
//endwork();
}

void f1(int a, int b);
void f2(float a, float b, float c);
void f3(char * a, bool b);

int main( int argc, char* argv[] )
{
Func( bind( f1 , 1,2) );
Func( bind( f2 , 1.0f,2.0f,3.0f) );
char* p = 0;
Func( bind( f3 , p,true) );
    return 0;
}


#3



void f1()
{
cout<<"Show()"<<endl;
}
void f2(int a, int b)
{
cout<<"a + b = "<<a + b<<endl;
}
void f3(char* ch)
{
cout<<ch<<endl;
}
typedef void (*Pf1)(void);
typedef void (*Pf2)(int a, int b);
typedef void (*Pf3)(char *ch);
union FunPtr
{
Pf1 fun1;
Pf2 fun2;
Pf3 fun3;
};
int main(int argc, char* argv[])
{
int a = 3;
int b = 4;
char* str = "Hello World!";

FunPtr fun;

fun.fun1 = (Pf1)f1;
fun.fun1();

fun.fun1 = (Pf1)f2;
fun.fun2(a, b);

fun.fun1 = (Pf1)f3;
fun.fun3(str);
system("pause");
return 0;
}


#4


F(fun_ptr)多个重载版本,也很烦。
可以讲参数抽象出来,比如

enum EArgType
{
    eTypeOne;
    eTypeTwo;
    // ...
};

struct ArgBase
{
    // ...
    EArgType _type; // 类型主要用来static_cast成对应的派生参数
};

struct ArgMore : public ArgBase
{
    // ...
};

typedef void (* PTR_FUN)( const ArgBase & arg );

void fun_a(const ArgBase & arg)
{
    ArgMore arg_more = static_cast<const ArgMore&>(arg);
    arg_more;
    // ... 
}

void Fun( PTR_FUN fun, const ArgBase & arg )
{
    // step one
    // ...

    // step two
    fun(arg);

    // ...
}

int main()
{
    ArgMore arg;
    // 填充arg
    Fun(fun_a, arg);

    // ...

    return 0;
}

#5


引用 2 楼 akirya 的回复:
tr1中的bind

例如VS2008 sp1
C/C++ code


#include<functional>
using namespace std;
using namespace tr1;

void Func( function<void()> f)
{
    //准备工作
    //prepare();

    f();
    //结束工作
    //endwor……


这个最好了

#6


请参考:
函数指针的几种用法 中“函数指针作为参数”的那部分。

#7


多谢各位,不好意思,一段时间断网了。手机只能看贴,登陆不上。

1楼好像没看懂问题
2楼的确实是好方法,但不幸我用的是vc2005...泪奔
3楼的没有解决根本问题
4楼的方法和我说的那个“不算办法的办法”本质上一样

我的问题已经解决,用va_list解决的,就是类似于printf传参的那种办法。