搜尋

首頁  >  問答  >  主體

c++ - 重载箭头运算符返回对象的地址而非对象?

C++ Primer, Fifth Edition:这个类的最后一行,为何返回的是地址?我一直觉得应该是return this->operator*(); 才对啊。不是说p->mem(*p).mem应该是一样的吗?

class StrBlobPtr 
{
public:
    std::string& operator*() const    
    { 
        auto p = check(curr, "dereference past end");   
        return (*p)[curr];  // (*p) is the vector to which this object points    
    }    
    std::string* operator->() const    
    {
         // delegate the real work to the dereference operator     
         return & this->operator*();    
    }    // other members as before 
};

The dereference operator checks that curr is still in range and, if so, returns a reference to the element denoted by curr. The arrow operator avoids doing any work of its own by calling the dereference operator and returning the address of the element returned by that operator.

大家讲道理大家讲道理2803 天前750

全部回覆(1)我來回復

  • PHP中文网

    PHP中文网2017-04-17 13:06:07

    請看代碼:定義了3個類,C包含B,B包含A。 A、B、C都定義了一個action的成員函數。 B和C都重載箭頭操作符,不同的是B的重載箭頭操作符回傳的是A類物件的指針,而C的重載箭頭運算子回傳的是B類物件(也就是你的疑問所在地)。

    #include <iostream>
    using namespace std;
    
    class A{
    public:
        A()    { x = 1;}
        void action(){
            cout << "Action in class A!" << endl;
        }
    
    public:
        int x;
    };
    
    class B{
        A a;
    public:
        B()    { x =2; }
        A* operator->(){
            return &a;
        }
        void action(){
            cout << "Action in class B!" << endl;
        }
    private:
        int x;
    };
    
    class C{
        B b;
    public:
        C (){ x =3; }
        B operator->(){
            return b;
        }
        void action(){
            cout << "Action in class C!" << endl;
        }
    private:
        int x;
    };
    
    int main(int argc, char *argv[])
    {
        C* pc = new C;
        pc->action();
        C c;
        c->action();
        int x = c->x;  
        std::cout<<x;
    
        getchar();
        return 0;
    }
    

    程式的輸出:
    Action in class C!
    Action in class A!
    1
    第一個輸出比較好理解,就不解釋了。對於第二個輸出和第三個輸出比較奇怪,為什麼會是這樣我們來看看官方的約定描述:

    重載箭頭操作符必須傳回指向類別類型的指針,或傳回定義了自己的箭頭操作符的類別類型物件。

    如果返回類型是指針,則內建箭頭操作符可用於該指針,編譯器對該指針引用並從結果對象取得指定成員。如果被指向的類型沒有定義那個成員,則編譯器產生一個錯誤。

    如果傳回類型是類別類型的其他物件(或是這種物件的參考),則將遞歸套用該操作符。編譯器檢查回傳物件所屬類型是否具有成員箭頭,如果有,就套用那個運算元;否則,編譯器產生錯誤。這個過程繼續下去,直到傳回一個指向具有指定成員的物件的指針,或傳回某些其他值,在後一種情況下,程式碼出錯。

    這解釋了上面的操作c->action();的輸出,因為c-> 返回的是B類型而不是指針,所有程式會迭代操作B類型的->重載函數,此時返回的是A型別指針,那麼此時不再迭代下去找到A的action()函數。如果A沒有action()函數,就會出錯。所以c->action();這句程式碼的實際運行是這樣的:c.operator->().operator->()->action();第三個輸出也是同理c->x;實際運行是c.operator->().operator->()->x ,所有即使C 的x 變數是private 也不會影響程序,甚至警告都不會。

    在你的程式中如果返回的不是指針,那麼程式會迭代查找std::string的->操作該操作返回的就是你執行StrBlobPtr-> 操作的回傳值,你覺得這是不是你希望的呢?也就是說如果返回的是類型而不是指針-> 會無限迭代下去直到返回的是指針然後再調用你開始指定的方法或者成員變量,這就是->所特有的不同的地方。

    回覆
    0
  • 取消回覆