我只是在学习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报道的那样。首先,我没有正确调用函数,因为编译器坚持使用。*或 - > *。不知道如何纳入此请求,欢迎任何帮助。现在,我可以通过使方法静态使用c样式指针或传递对象并从Next中调用方法来解决我的问题,但我想理解指向方法的指针。基本上,我很困惑为什么一个。添加不是一个可接受的输入。调用方法是明确定义的(.Add)并符合我的typedef。另外,我从typedef提供了类(一)的实例,从而提供了执行方法的上下文。但编译器输出看起来像我不仅错过了语法,但我错过了这个概念。那么,如何将指向对象的方法作为上下文作为单个参数传递?
答案 0 :(得分:6)
这里的主要问题是成员函数与对象实例没有关联,它们只是具有略微不同签名的函数指针。
因此,当你想调用一个成员函数时,你需要做两件事:一个指向成员函数的指针和对象实例来调用它。
我稍微更改了您的代码示例:
#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;
}
现在it works。它可能会有所改进,但我认为你可以从这里开始。
我建议您阅读Pointers to member functions的c++ faq lite部分,这很好地解释了这一点。
答案 1 :(得分:1)
那么,如何将指向对象的方法作为上下文作为单个参数传递?
只使用成员函数指针,你不能。虽然你的语法看起来应该这样做,但是不允许这样做。您需要一个对象将该函数应用于:
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
(或boost::bind
如果你不能使用C ++ 11还):
#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);
答案 2 :(得分:0)
指向成员的指针需要一个实例来操作。本质上,它们是带有一个加法参数的函数,该参数成为隐式this
指针。要通过指向当前对象的成员的指针来调用函数,可以使用如下代码:
(this->*funct)(c, 1);
(您可以类似地访问成员变量但没有函数调用)。
您调用该成员的对象不是指向成员的指针的一部分。因此,你需要得到这样的东西:
&One::Add
如果成员函数过载,这会变得更有趣:在这种情况下,您需要提供一个上下文,从中可以在获取地址时确定重载。我为此愚蠢地使用static_cast<>()
:
static_cast<int (One::*)(int,int)>(&One::Add)
答案 3 :(得分:0)
这里有一堆问题:one.Add
是一个成员函数
你不能只是调用它。你需要有一个指向类的指针
也可以调用它。此外,您需要使用特殊operator.*
或operator->*
。您也不能获取绑定成员的地址
功能
总而言之,您应该使用模板和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;
}