[英]Pointer-to-member-function error
我試圖在代碼中使用指向成員函數的指針,以便可以輕松替換要使用的函數,而無需在代碼中的任何地方進行更改。 編譯時出現錯誤,我不知道如何解決。 這是一個最小的工作示例:
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
如果我在ExecuteFunction
中用FunctionToUse
替換(*m_matchingAlgorithm)
,則代碼將編譯而不會出錯。
將函數調用更改為:
(this->*m_matchingAlgorithm)(order, listOfOrders);
您可以使用指向成員運算符( .*
或->*
)的指針來調用函數:
void OrderBook::ExecuteFunction(Order & order, std::list<Order> listOfOrders)
{
(this->*m_matchingAlgorithm)(order, listOfOrders);
}
更多信息在這里 。
我們都習慣於省略this->
來訪問當前對象的成員。 允許這樣做的機制是名稱解析原則。 但是這些不適用於指針解引用運算符。
指向數據成員的指針的簡單情況
讓我們來看一個簡單的例子:一個指向整數成員的指針。
class OrederBook {
...
int x,y;
int OrderBook::* px;
};
在構造函數中,您無法使用&x
初始化px
,因為&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: 一元 *運算符執行間接操作:應用該表達式的表達式應是指向對象類型的指針或指向函數類型的指針,並且結果是指向對象或函數的左值表達點。 如果表達式的類型為“ T的指針”,則結果的類型為“ T”。
5.5 / 3: 二進制運算符-> *將其第二個操作數綁定到其第一個操作數,第二個操作數應為“指向T的成員的指針”類型,而其第二個操作數應為“指向T的指針”或“其指向一個類別的指針”表達式E1-> E2轉換為等效形式( (E1))。* E2。
解引用指向成員函數的指針
對於上面的數據示例,您可以選擇武器。 您可以很容易地構建代碼來獲得相同的結果,但是將px
定義為int *px
而不是int OrderBook::*px
並照常使用一元*
。
不幸的是,對於非靜態成員函數的支持者,您不能使用此類快捷方式。 您實際上確實需要一個指向成員函數的指針,而不是指向函數的指針:當您調用成員函數時,除了必須傳遞的參數之外,您始終必須知道為哪個對象調用它。 唯一的方法就是使用(->*)
或(.*)
。
結論
忽略this- this->*
並假設編譯器足夠智能,可以推斷出當前對象是對我們來說似乎很自然。 但這不是標准定義的。 不幸的是, 這里還有更多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.