我正在尝试在我的代码中使用指向成员函数的指针,以便我可以轻松地替换要使用的函数,而无需更改代码中的任何位置。编译时我得到一个错误,我不明白如何解决。以下是最低工作示例:
OrderBook.h
#include <list>
#include <string>
class Order
{
};
class OrderBook
{
typedef void(OrderBook::* MatchingAlgorithm)(Order&, std::list<Order>&);
public:
OrderBook(const std::string name);
void ExecuteFunction(Order&, std::list<Order>);
private:
void FunctionToUse(Order&, std::list<Order>&);
const std::string m_OrderBookName;
MatchingAlgorithm m_matchingAlgorithm;
};
OrderBook.cpp
#include "OrderBook.h"
OrderBook::OrderBook(
const std::string name
)
: m_OrderBookName(name)
{
m_matchingAlgorithm = &OrderBook::FunctionToUse;
}
void OrderBook::ExecuteFunction(Order & order, std::list<Order> listOfOrders)
{
(*m_matchingAlgorithm)(order, listOfOrders);
}
void OrderBook::FunctionToUse(Order &, std::list<Order>&)
{
// do nothing
}
Source.cpp
#include "OrderBook.h"
int main()
{
std::list<Order> mylist;
Order o1, o2;
mylist.push_back(o1);
mylist.push_back(o2);
OrderBook ob("my book");
ob.ExecuteFunction(o1, mylist);
return 0;
}
编译错误
error C2171: '*': illegal on operands of type 'OrderBook::MatchingAlgorithm'
error C2064: term does not evaluate to a function taking 2 arguments
如果我将(*m_matchingAlgorithm)
替换为FunctionToUse
ExecuteFunction
,则代码编译时没有错误。
答案 0 :(得分:2)
将函数调用更改为:
(this->*m_matchingAlgorithm)(order, listOfOrders);
答案 1 :(得分:2)
您可以使用指向成员运算符(.*
或->*
)的指针调用您的函数:
void OrderBook::ExecuteFunction(Order & order, std::list<Order> listOfOrders)
{
(this->*m_matchingAlgorithm)(order, listOfOrders);
}
更多信息here。
我们都习惯于省略this->
来访问当前对象的成员。允许这种情况的机制是名称解析原则。但这些不适用于指针解除引用运算符。
指向数据成员的指针的简单情况
让我们用更简单的情况加注星形:指向整数成员的指针。
class OrederBook {
...
int x,y;
int OrderBook::* px;
};
在构造函数中,您无法使用px
初始化&x
,因为&x
是整数的绝对地址,px
是一个(相对)地址OrderBook
中的整数。然后我们会初始化它:
OrderBook::OrderBook(..)
: m_OrderBookName(name), px(&OrderBook::x) {...}
但在这种情况下,px
的普通解除引用运算符也不起作用:
*px =2; // error because of unary operator *
实际上,对于解除引用这样的指针,您不仅需要知道指针,还需要知道应该使用此指针的对象:
this->*px =2; // yes ! take relative px address and apply it to this object.
一元与二元反对
该标准定义了两个不同的解除引用运算符:
5.3.1 / 1: 一元 *运算符执行间接:表达式 应用应该是指向对象类型的指针,或指向a的指针 函数类型,结果是引用对象或的左值 表达式指向的函数。如果是表达式的类型 是“指向T的指针”,结果的类型是“T”。
5.5 / 3: 二进制运算符 - &gt; *将其第二个操作数绑定到第一个操作数,该操作数应为“指向T成员的指针”,哪一个 应为“指向T的指针”或“指向T所属的类的指针” 一个明确的,可访问的基类。“表达式E1-&gt; E2是 转换为等效形式((E1))。* E2。
取消引用指向成员函数的指针
对于上面的数据示例,您可以选择武器。您可以非常轻松地构建实现相同结果的代码,但将px
定义为int *px
而不是int OrderBook::*px
并像往常一样使用一元*
。
不幸的是,对于非静态成员函数的poitners,你不能使用这样的快捷方式。你真的需要一个指向成员函数的指针而不是指向函数的指针:当你调用一个成员函数时,除了你必须传递的参数之外,你总是要知道你调用它的对象。告诉他们的唯一方法是使用(->*)
或(.*)
。
<强>结论强>
忽略this->*
并假设编译器足够聪明,可以推断它对于当前对象来说对我们来说似乎很自然。但这并不是标准所定义的。这是不幸的,更多here。