3

當與類的成員函數指針的處理,我們可以調用一個函數的對象實例的語法如下:調用一個成員函數指針的智能指針

struct X { 
    void foo(); 
}; 

X x;    // Instance 
auto f = &X::foo; // Member function pointer 

(x.*f)();   // Call function f on x 

有一個實例的原始指針時,語法是這樣的:

X *xptr = new X(); 

(xptr->*f)(); 

這很好地遵循靜態函數調用的比喻:

x.foo(); 
x->foo(); 

然而,當我有類的智能指針,這不起作用:

unique_ptr<X> xsptr(new X()); 

(xsptr->*f)(); // g++: error: no match for 'operator->*' in 'xsptr ->* f' 

我解決這個問題,首先應用對其操作,然後用.語法調用:

((*xsptr).*f)(); 

這是多醜?

編譯器是否應該拒絕上面的箭頭語法?因爲通常(靜態調用函數時),它會調用operator ->。不應該->*也只能撥打operator ->

編譯器錯誤部分回答了這個問題:錯誤讀取,我們可以重載operator ->*調用一個成員函數指針解除引用的對象,這unique_ptr不上。但是這引入了更多的問題。爲什麼智能指針不這樣做,如果語言需要這個?它是否打算而不是這樣做,因爲它引入了其他問題?爲什麼我們必須寫這個運算符而不是隱式地調用->返回的對象上的成員函數指針呢? (因爲這是編寫xsptr->foo()時的行爲)

+0

爲什麼' - > *'爲非指針值會做什麼?編譯器不知道'unique_ptr'試圖模仿原始指針。 'operator - > *'是可重載的,但是乾淨地實現它卻很煩人。 – Xeo 2013-03-25 12:30:11

+0

@Xeo我的意思是,標準可以很好地定義' - > *'的默認行爲,即「調用'operator->'」返回的對象上的成員指針,如下所示:'operator - > *(memptr){return((* this) - >)。* memptr(); }'。但是由於它不*這樣做,爲什麼C++ 11中的指針類型沒有定義這個運算符?有理由嗎? – leemes 2013-03-25 12:31:57

+0

嗯,我想這也適用於C++ 03。 – leemes 2013-03-25 12:33:49

回答

3

編譯器是否應該拒絕上面的箭頭語法?因爲通常(靜態調用函數時),它會調用operator - >。不應該 - > *也只是調用operator - >?

編譯器正確拒絕語法。沒有operator->*不應該叫operator->(根據標準)。請注意,雖然語法可能看起來類似,但->*本身就是一個運營商,而不是->與其他一些*東西的組成。

+0

到目前爲止這麼好。我剛剛瞭解到這一點,謝謝! :)但是:如何一致地解決這個問題?假設我有一個模板參數'T',它既可以是一個原始指針,也可以是一個智能指針,'t'是該實例的一個實例,'f'是指向't'的指針。我現在寫'((* t)。* f)()'這很醜,但似乎工作。 – leemes 2013-03-25 12:42:03

+0

@lemes:'auto&obj = * p; (obj。* f)(stuff ...)' – Xeo 2013-03-25 12:43:06

+0

@Xeo這是一樣的,不是嗎? (比方說,我只需要這個單一表達式的解除引用對象。) – leemes 2013-03-25 12:44:08

0

您可以爲智能指針重載operator->*。見Scott Meyers的文章this。其基本思想是返回一個函數對象,該對象在從操作員返回後將被調用。

該文章有點過時了,您現在可以使用變量函數參數編號的一個可變參數模板。

+0

我不能重載現有的智能指針實現的操作符... – leemes 2015-12-11 08:55:57

+0

當然你可以!你只需要在課堂外定義它。例如,對於unique_ptr,代碼將如下所示: 'template const PMFC 運算符 - > *(const std :: unique_ptr &pObj,ReturnType(T :: * pmf)()) { \t return std :: make_pair(pObj.get(),pmf); }' – 2015-12-14 16:39:59