2016-09-27 93 views
3
struct A { 
    int i; 
}; 

struct B { 
    A a; 

    operator A*() { return &a; } 
}; 

int main(int argc, char *argv[]) 
{ 
    B b; 

    return b->i; 
} 

g++報告error: base operand of ‘->’ has non-pointer type ‘B’爲什麼這個類不會隱式轉換爲指針?

爲什麼?我已經想出瞭如何規避這個問題(使用operator->),但我不明白爲什麼隱式轉換不會發生。

回答

5

這是重載決策是如何爲->運營商定義的結果。從C++ 14 [over.match.oper]/3引述:

對於操作者,,一元運算符&,或者操作員->,內置的候選集是空的。

也就是說,如果->左側的操作數是類或枚舉類型,那麼->將永遠不會有其內置的意義;相反,名稱查找operator->作爲左側操作數的類的成員必須成功。

如果內置->運營商是一個候選,那麼編譯器可以考慮隱式轉換,將允許B轉換到內置->可以採取一種類型,但它不是一個候選人,從而使不會發生。

3

因爲C++只會在知道它應該轉換爲什麼時隱式轉換類實例。如果使用這樣的表達式b->,它無法知道什麼指針類型(如果有的話),你會想將它轉換爲,並只使用正常的操作符(除非重載未定義):

B b; 

// calls B::operator-> since that's what you tell it to do 
b->i; 

// calls B::operator A* since it knows it's implicitly converting to A* 
A *a = b; 

如果你想在這裏使用的第一個表情,正確方式是重載operator->

class B { 
    /* ... */ 

    A* operator ->() { return &a; } 
} 
3

但我不明白爲什麼隱式轉換不會發生。

沒有上下文可以發生。operator->隱式適用於指針或指定了該運算符的類類型。但就是這樣。編譯器沒有其他的順序來尋找它。在這種情況下,b->的內置候選集是空的,沒有operator->,因此編譯錯誤。

你只想補充:

A* operator->() { return &a; } 
相關問題