指向方法的指针出现问题

Troubles with pointer to methods

本文关键字:问题 指针 方法      更新时间:2023-10-16

我刚刚在学习C++,在指向方法的指针方面遇到了困难。比方说:

class One {
public:
int Add (int a, int b) {return a+b;}
};
typedef int (One::*pAdd) (int, int);
class Other {
public:
int Next (pAdd funct, int c){ return funct (c, 1);}
};
int main (){
One one;
Other other;
other.Next(one.Add, 2);
return 0;
}

据我的MinGW报道,我有很多问题。首先,我没有正确调用funct,因为编译器坚持使用.*或->*。不知道如何合并此请求,欢迎任何帮助。现在,我可以通过使方法静态来使用c样式指针或从Next中传递对象和调用方法来解决我的问题,但我想了解指向方法的指针。基本上,我很困惑为什么会这样。添加是不可接受的输入。要调用的方法是明确定义的(.Add),并且符合我的typedef。另外,我从typedef中提供类(one)的实例,从而提供要在其中执行方法的上下文。但编译器输出看起来我不仅错过了语法,而且错过了概念。那个么,如何将指针传递给将对象作为上下文的方法作为单个参数呢?

这里的主要问题是成员函数与对象实例不关联,它们只是签名略有不同的函数指针。

因此,当您想要调用成员函数时,您需要两件事:指向成员函数的指针和调用它的object实例

我更改了您的代码示例:

#include <iostream>
class One {
public:
    int Add (int a, int b) {return a+b;}
};
typedef int (One::*pAdd) (int, int);
class Other {
public:
    int Next (One one, pAdd funct, int c){
        return (one.*funct)(c, 1);
    }
};
int main (){
    One one;
    Other other;
    std::cout << other.Next(one, &One::Add, 2) << std::endl;
    return 0;
}

现在它起作用了。它可能会有所改进,但我认为你可以从这里开始。

我建议您阅读c++faq-lite的Pointers to member functions一节,它很好地解释了这一点。

那个么,如何将指针传递给将对象作为上下文的方法作为单个参数呢?

只使用成员函数指针是不行的。尽管您的语法看起来应该这样做,但这是不允许的。您需要一个对象来将函数应用于:

class Other {
public:
    int Next (pAdd funct, One & o, int c){ return (o.*funct) (c, 1);}
}
int main (){
    One one;
    Other other;
    other.Next(&One::Add, one, 2);
}

如果您想创建一个调用特定对象的特定成员函数的函数对象,那么一种可能性是使用std::bind(如果您还不能使用C++11,则使用boost::bind):

#include <functional>
class Other {
public:
    int Next (std::function<int(int,int)> funct, int c){ return funct (c, 1);}
};
int main (){
    One one;
    Other other;
    using namespace std::placeholders;
    other.Next(std::bind(&One::Add, &one, _1, _2), 2);
}

或lambda:

other.Next([&](int a, int b){return one.Add(a,b);}, 2);

指向成员的指针需要一个实例来操作。本质上,它们是接受一个加法参数的函数,该参数将成为隐式this指针。要通过指向当前对象成员的指针调用函数,可以使用以下代码:

(this->*funct)(c, 1);

(您可以类似地访问成员变量,但不需要函数调用)。

调用成员的对象不是指向成员的指针的一部分。因此,你需要得到这样的东西:

&One::Add

如果成员函数被重载,这会变得更有趣:在这种情况下,您需要提供一个上下文,在获取地址时可以从中确定重载。我两次使用static_cast<>()

static_cast<int (One::*)(int,int)>(&One::Add)

这里有很多问题:one.Add是一个成员函数你不能只调用它。你需要有一个指向也调用它。此外,您需要使用特殊的operator.*或CCD_ 7。您也不能获取绑定成员的地址作用

总之,您应该使用模板和boost/std::bind所有这些都可以忍受,或者远离它。

此处已修改,工作代码:

class One {
public:
  int Add (int a, int b) {return a+b;}
};
typedef int (One::*pAdd) (int, int);
class Other {
public:
  int Next (One* one, pAdd funct, int c){ return (one->*funct)(c, 1);}
};
int main (){
  One one;
  Other other;
  other.Next(&one, &One::Add, 2);
  return 0;
}