简体   繁体   English

指针到成员功能错误

[英]Pointer-to-member-function error

I am trying to use a pointer to a member function in my code so that I can easily replace the function to use without changing everywhere in the code. 我试图在代码中使用指向成员函数的指针,以便可以轻松替换要使用的函数,而无需在代码中的任何地方进行更改。 I get an error while compiling that I don't understand how to solve. 编译时出现错误,我不知道如何解决。 Here is a minimum working example: 这是一个最小的工作示例:

OrderBook.h 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 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 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;
}

Compilation Errors 编译错误

error C2171: '*': illegal on operands of type 'OrderBook::MatchingAlgorithm'
error C2064: term does not evaluate to a function taking 2 arguments

If I replace (*m_matchingAlgorithm) with FunctionToUse inside ExecuteFunction the code compiles without errors. 如果我在ExecuteFunction中用FunctionToUse替换(*m_matchingAlgorithm) ,则代码将编译而不会出错。

将函数调用更改为:

(this->*m_matchingAlgorithm)(order, listOfOrders);

Short answer 简短答案

You can call your function using the pointer to member operator ( .* or ->* ): 您可以使用指向成员运算符( .*->* )的指针来调用函数:

void OrderBook::ExecuteFunction(Order & order, std::list<Order> listOfOrders)
{
    (this->*m_matchingAlgorithm)(order, listOfOrders);
}

More info here . 更多信息在这里

Long explanations 详细说明

We are all used to omit this-> for accessing members of the current object. 我们都习惯于省略this->来访问当前对象的成员。 The mecanism that allows this is name resolution principles. 允许这样做的机制是名称解析原则。 But these do not apply for pointer dereferencing operators. 但是这些不适用于指针解引用运算符。

The simple case of a pointer to a data member 指向数据成员的指针的简单情况

Let's star with a simpler case : a pointer to an integer member. 让我们来看一个简单的例子:一个指向整数成员的指针。

class OrederBook {
    ...
    int x,y; 
    int OrderBook::* px; 
};

In the constructor you couldn't initialize px with &x because &x is an absolute address of an integer, and px is the (relative) address of an integer in an OrderBook . 在构造函数中,您无法使用&x初始化px ,因为&x是整数的绝对地址,而pxOrderBook整数的(相对)地址。 We would then initialize it: 然后我们将其初始化:

OrderBook::OrderBook(..)
    : m_OrderBookName(name), px(&OrderBook::x) {...}

But in this case, the ordinary dereferencing operator for px would not work either: 但是在这种情况下, px的普通解引用运算符也不起作用:

 *px =2;    // error because of unary operator *

In fact, for dereferencing such a pointer, you need to know not only the pointer, but also the object in which this pointer should be used: 实际上,要取消引用此类指针,您不仅需要知道该指针,还需要知道该指针应在其中使用的对象:

 this->*px =2;    // yes ! take relative px address and apply it to this object.  

Unary vs. Binary derefencing 一元与二进制解引用

The standard defines two different dereferencing operators: 该标准定义了两个不同的解引用运算符:

5.3.1/1: The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. 5.3.1 / 1: 一元 *运算符执行间接操作:应用该表达式的表达式应是指向对象类型的指针或指向函数类型的指针,并且结果是指向对象或函数的左值表达点。 If the type of the expression is “pointer to T,” the type of the result is “T.” 如果表达式的类型为“ T的指针”,则结果的类型为“ T”。

5.5/3: The binary operator ->* binds its second operand, which shall be of type “pointer to member of T” to its first operand, which shall be of type “pointer to T” or “pointer to a class of which T is an unambiguous and accessible base class.” The expression E1-> E2 is converted into the equivalent form ( (E1)).*E2. 5.5 / 3: 二进制运算符-> *将其第二个操作数绑定到其第一个操作数,第二个操作数应为“指向T的成员的指针”类型,而其第二个操作数应为“指向T的指针”或“其指向一个类别的指针”表达式E1-> E2转换为等效形式( (E1))。* E2。

Dereferencing a pointer to a member function 解引用指向成员函数的指针

For the data example above, you have the choice of the weapons. 对于上面的数据示例,您可以选择武器。 You could build very easily code achieving the same results, but defining px as int *px instead of int OrderBook::*px and using the unary * as usual. 您可以很容易地构建代码来获得相同的结果,但是将px定义为int *px而不是int OrderBook::*px并照常使用一元*

Unfortunately for poitners to non static member function, you can't use such shortcuts. 不幸的是,对于非静态成员函数的支持者,您不能使用此类快捷方式。 You really need a pointer to a member function and not a pointer to a function: When you call a member function, in addition to the arguments that you have to pass, you always have to know for which object you call it. 您实际上确实需要一个指向成员函数的指针,而不是指向函数的指针:当您调用成员函数时,除了必须传递的参数之外,您始终必须知道为哪个对象调用它。 And the only way to tell this is to use (->*) or (.*) . 唯一的方法就是使用(->*)(.*)

Conclusion 结论

Ommitting this->* and assuming the compiler would be intelligent enough to deduct that it's for the current object could seem natural for us. 忽略this- this->*并假设编译器足够智能,可以推断出当前对象是对我们来说似乎很自然。 But this is not defined by the standard. 但这不是标准定义的。 It's unfortunate and more here . 不幸的是, 这里还有更多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM