search

Home  >  Q&A  >  body text

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.

大家讲道理大家讲道理2767 days ago732

reply all(1)I'll reply

  • PHP中文网

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

    Please look at the code: 3 classes are defined, C contains B, and B contains A. A, B, and C all define an action member function. Both B and C overload the arrow operator. The difference is that the overloaded arrow operator of B returns a pointer to a class A object, while the overloaded arrow operator of C returns an object of class B (that is, where your question is). ).

    #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;
    }
    

    Output of the program:
    Action in class C!
    Action in class A!
    1
    The first output is easier to understand, so I won’t explain it. The second and third outputs are strange. Why are they like this? Let’s take a look at the official agreement description:

    Overloaded arrow operators must return a pointer to a class type, or an object of a class type that defines its own arrow operator.

    If the return type is a pointer, the built-in arrow operator can be used on the pointer, and the compiler dereferences the pointer and obtains the specified member from the result object. If the type pointed to does not define that member, the compiler generates an error.

    If the return type is another object of class type (or a reference to such an object), the operator will be applied recursively. The compiler checks whether the type of the returned object has a member arrow, and if so, applies that operator; otherwise, the compiler generates an error. This process continues until a pointer to an object with the specified members is returned, or some other value is returned, in which case the code errors.

    This explains the output of the above operation c->action();, because c-> returns type B instead of a pointer, and all programs will iteratively operate the -> overloaded function of type B, What is returned at this time is a pointer of type A, so there is no need to iterate to find the action() function of A at this time. If A does not have an action() function, an error will occur. So the actual operation of the code c->action(); is as follows: c.operator->().operator->()->action(); The third output is the same as c- >x;The actual operation is c.operator->().operator->()->x, so even if the x variable of C is private, it will not affect the program, and there will not even be a warning.

    If what is returned in your program is not a pointer, then the program will iterately search for the -> operation of std::string. This operation returns the return value of the StrBlobPtr-> operation. Do you think this is your What do you hope? In other words, if a type is returned instead of a pointer -> will iterate indefinitely until a pointer is returned and then the method or member variable you specified at the beginning will be called. This is the unique difference of -> .

    reply
    0
  • Cancelreply