C++ 指向成员函数的函数指针

C++ 指向成员函数的函数指针,c++,oop,function-pointers,C++,Oop,Function Pointers,我想将函数指针设置为类的成员,该类是指向同一类中另一个函数的指针。我这么做的原因很复杂 在本例中,我希望输出为“1” 但这在编译时失败了。为什么?语法错误。成员指针是与普通指针不同的类型类别。成员指针必须与其类的对象一起使用: class A { public: int f(); int (A::*x)(); // <- declare by saying what class it is a pointer to }; int A::f() { return 1; } int

我想将函数指针设置为类的成员,该类是指向同一类中另一个函数的指针。我这么做的原因很复杂

在本例中,我希望输出为“1”


但这在编译时失败了。为什么?

语法错误。成员指针是与普通指针不同的类型类别。成员指针必须与其类的对象一起使用:

class A {
public:
 int f();
 int (A::*x)(); // <- declare by saying what class it is a pointer to
};

int A::f() {
 return 1;
}


int main() {
 A a;
 a.x = &A::f; // use the :: syntax
 printf("%d\n",(a.*(a.x))()); // use together with an object of its class
}
A类{
公众:
int f();

int(A::*x)(;//您需要使用指向成员函数的指针,而不仅仅是指向函数的指针

class A { 
    int f() { return 1; }
public:
    int (A::*x)();

    A() : x(&A::f) {}
};

int main() { 
   A a;
   std::cout << (a.*a.x)();
   return 0;
}
A类{
int f(){return 1;}
公众:
int(A::*x)();
A():x(&A::f){}
};
int main(){
A A;
std::cout
int(*x)(
不是指向成员函数的指针。指向成员函数的指针是这样写的:
int(a::*x)(void)=&a::f;

#包括
#包括
甲级
{
公众:
无效调用();
私人:
void printH();
void命令(std::stringa,std::stringb,void(a::*func)();
};
void A::printH()
{
std::cout*func)();
}
}
int main()
{
A A;
a、 call();
返回0;
}

请注意
(this->*func)(;
以及用类名声明函数指针的方法
void(A::*func)(
虽然这是基于本页其他地方的sterling答案,但我有一个用例,它们并没有完全解决;对于指向函数的指针向量,请执行以下操作:

#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>

class A{
public:
  typedef vector<int> (A::*AFunc)(int I1,int I2);
  vector<AFunc> FuncList;
  inline int Subtract(int I1,int I2){return I1-I2;};
  inline int Add(int I1,int I2){return I1+I2;};
  ...
  void Populate();
  void ExecuteAll();
};

void A::Populate(){
    FuncList.push_back(&A::Subtract);
    FuncList.push_back(&A::Add);
    ...
}

void A::ExecuteAll(){
  int In1=1,In2=2,Out=0;
  for(size_t FuncId=0;FuncId<FuncList.size();FuncId++){
    Out=(this->*FuncList[FuncId])(In1,In2);
    printf("Function %ld output %d\n",FuncId,Out);
  }
}

int main(){
  A Demo;
  Demo.Populate();
  Demo.ExecuteAll();
  return 0;
}
#包括
#包括
#包括
#包括
甲级{
公众:
typedef向量(A::*AFunc)(inti1,inti2);
向量函数表;
内联int减法(inti1,inti2){返回I1-I2;};
内联int-Add(inti1,inti2){返回I1+I2;};
...
空填充();
void ExecuteAll();
};
void A::Populate(){
FuncList.push_back(&A::Subtract);
FuncList.push_back(&A::Add);
...
}
void A::ExecuteAll(){
intin1=1,In2=2,Out=0;
对于(size_t FuncId=0;FuncId*FuncList[FuncId])(In1,In2);
printf(“函数%ld输出%d\n”,FuncId,Out);
}
}
int main(){
演示;
Demo.Populate();
Demo.ExecuteAll();
返回0;
}

如果您正在编写一个带有索引函数的命令解释器,该命令解释器需要与参数语法和帮助提示等结合在一起。在菜单中可能也很有用。

不幸的是,您无法将现有成员函数指针转换为普通函数指针,您可以以一种相当简单的方式创建适配器函数模板,将编译时已知的成员函数指针封装到普通函数中,如下所示:

template <class Type>
struct member_function;

template <class Type, class Ret, class... Args>
struct member_function<Ret(Type::*)(Args...)>
{
    template <Ret(Type::*Func)(Args...)>
    static Ret adapter(Type &obj, Args&&... args)
    {
        return (obj.*Func)(std::forward<Args>(args)...);
    }
};

template <class Type, class Ret, class... Args>
struct member_function<Ret(Type::*)(Args...) const>
{
    template <Ret(Type::*Func)(Args...) const>
    static Ret adapter(const Type &obj, Args&&... args)
    {
        return (obj.*Func)(std::forward<Args>(args)...);
    }
};
模板
结构成员函数;
模板
结构成员函数
{
模板
静态Ret适配器(类型和对象、参数和…参数)
{
返回(obj.*Func)(标准::转发(args)…);
}
};
模板
结构成员函数
{
模板
静态Ret适配器(常量类型和对象、参数和…参数)
{
返回(obj.*Func)(标准::转发(args)…);
}
};

int(*func)(A&)=&member\u函数::适配器;

请注意,为了调用成员函数,必须提供
A
的实例。

基于@IllidanS4的答案,我创建了一个模板类,它允许通过引用传递几乎所有具有预定义参数的成员函数和类实例,以供以后调用


模板类回调{
公众:
虚拟RET呼叫(RArgs&…RArgs)=0;
//虚拟RET调用()=0;
};
模板类CallbackCalltimeArgs:公共回调\u t{
公众:
业主;
RET(T::*x)(RArgs…);
RET呼叫(RArgs&…RArgs){
返回(*owner.*(x))(标准:远期(rargs)…);
};
CallbackCalltimeArgs(T*T,RET(T::*x)(RArgs…):所有者(T),x(x){}
};
模板类CallbackCreattimeArgs:公共回调\u t{
公众:
业主;
RET(T::*x)(Args…);
retcall(){
return(*owner.*(x))(std::get(args)…);
};
std::元组参数;
CallbackCreattimeArgs(T*T,RET(T::*x)(Args…,Args&&…Args):所有者(T),x(x),
args(std::tuple(std::forward(args)…){}
};
测试/示例:

class container {
public:
    static void printFrom(container* c) { c->print(); };
    container(int data) : data(data) {};
    ~container() {};
    void print() { printf("%d\n", data); };
    void printTo(FILE* f) { fprintf(f, "%d\n", data); };
    void printWith(int arg) { printf("%d:%d\n", data, arg); };
private:
    int data;
};

int main() {
    container c1(1), c2(20);
    CallbackCreattimeArgs<container, void> f1(&c1, &container::print);
    Callback_t<void>* fp1 = &f1;
    fp1->call();//1
    CallbackCreattimeArgs<container, void, FILE*> f2(&c2, &container::printTo, stdout);
    Callback_t<void>* fp2 = &f2;
    fp2->call();//20
    CallbackCalltimeArgs<container, void, int> f3(&c2, &container::printWith);
    Callback_t<void, int>* fp3 = &f3;
    fp3->call(15);//20:15
}
类容器{
公众:
静态void printFrom(container*c){c->print();};
容器(int-data):数据(data){};
~container(){};
void print(){printf(“%d\n”,data);};
void printTo(文件*f){fprintf(f,“%d\n”,数据);};
void printWith(int arg){printf(“%d:%d\n”,数据,arg);};
私人:
int数据;
};
int main(){
容器c1(1)、c2(20);
CallbackCreattimeArgs f1(&c1,&container::print);
回调函数*fp1=&f1;
fp1->call();//1
CallbackCreattimeArgs f2(&c2,&container::printTo,stdout);
回调函数*fp2=&f2;
fp2->call();//20
CallbackCalltimeArgs f3(&c2,&container::printWith);
回调函数_t*fp3=&f3;
fp3->呼叫(15);//20:15
}
显然,只有当给定的参数和所有者类仍然有效时,这才有效。就可读性而言。。。请原谅我

编辑:通过使元组正常存储,删除了不必要的malloc。为引用添加了继承的类型。添加了在calltime提供所有参数的选项。现在正在努力使两者兼而有之

按承诺编辑2:,两者都是。唯一的限制(我看到)是预定义的参数必须在回调函数中运行时提供的参数之前。感谢@Chipster对gcc合规性的帮助。这适用于ubuntu上的gcc和windows上的visual studio

\ifdef\u WIN32
#定义wintypename类型名称
#否则
#定义wintypename
#恩迪夫
模板类回调{
公众:
虚拟RET呼叫(RArgs…RArgs)=0;
virtual~Callback\u t()=默认值;
};
模板类CallbackFactory{
私人:
模板类回调:公共回调\u t{
私人:
业主;
RET(T::*x)(CArgs…,RArgs;
std::元组cargs;
RET呼叫(RArgs…RArgs){
return(*owner.*(x))(std::get
template <class Type>
struct member_function;

template <class Type, class Ret, class... Args>
struct member_function<Ret(Type::*)(Args...)>
{
    template <Ret(Type::*Func)(Args...)>
    static Ret adapter(Type &obj, Args&&... args)
    {
        return (obj.*Func)(std::forward<Args>(args)...);
    }
};

template <class Type, class Ret, class... Args>
struct member_function<Ret(Type::*)(Args...) const>
{
    template <Ret(Type::*Func)(Args...) const>
    static Ret adapter(const Type &obj, Args&&... args)
    {
        return (obj.*Func)(std::forward<Args>(args)...);
    }
};
int (*func)(A&) = &member_function<decltype(&A::f)>::adapter<&A::f>;
class container {
public:
    static void printFrom(container* c) { c->print(); };
    container(int data) : data(data) {};
    ~container() {};
    void print() { printf("%d\n", data); };
    void printTo(FILE* f) { fprintf(f, "%d\n", data); };
    void printWith(int arg) { printf("%d:%d\n", data, arg); };
private:
    int data;
};

int main() {
    container c1(1), c2(20);
    CallbackCreattimeArgs<container, void> f1(&c1, &container::print);
    Callback_t<void>* fp1 = &f1;
    fp1->call();//1
    CallbackCreattimeArgs<container, void, FILE*> f2(&c2, &container::printTo, stdout);
    Callback_t<void>* fp2 = &f2;
    fp2->call();//20
    CallbackCalltimeArgs<container, void, int> f3(&c2, &container::printWith);
    Callback_t<void, int>* fp3 = &f3;
    fp3->call(15);//20:15
}
std::string myString{ "Hello World!" };
auto memberFunctionPointer{ &std::string::length };
auto myStringLength{ (myString.*memberFunctionPointer)() };
std::invoke(memberFunctionPointer, myString);