Erasmus
Erasmus

Reputation: 427

The Arrow Member Operator in C++

I am quite new to using C++. I have handled Java and ActionScript before, but now I want to learn this powerful language. Since C++ grants the programmer the ability to explicitly use pointers, I am quite confused over the use of the arrow member operator. Here is a sample code I tried writing.

main.cpp:

   #include <iostream>
   #include "Arrow.h"
   using namespace std;

   int main()
   {
        Arrow object;
        Arrow *pter = &object;

        object.printCrap(); //Using Dot Access
        pter->printCrap(); //Using Arrow Member Operator
        return 0;
   }

Arrow.cpp

   #include <iostream>
   #include "Arrow.h"
   using namespace std;

   Arrow::Arrow()
   {

   }

   void Arrow::printCrap(){
       cout << "Steak!" << endl;
   }

In the above code, all it does is to print steak, using both methods (Dot and Arrow).

In short, in writing a real practical application using C++, when do I use the arrow notation? I’m used to using the dot notation due to my previous programming experience, but the arrow is completely new to me.

Upvotes: 6

Views: 10794

Answers (3)

Jerry Coffin
Jerry Coffin

Reputation: 490573

In C, a->b is precisely equivalent to (*a).b. The "arrow" notation was introduced as a convenience; accessing a member of a struct via a pointer was fairly common and the arrow notation is easier to write/type, and generally considered more readable as well.

C++ adds another wrinkle as well though: operator-> can be overloaded for a struct/class. Although fairly unusual otherwise, doing so is common (nearly required) for smart pointer classes.

That's not really unusual in itself: C++ allows the vast majority of operators to be overloaded (although some almost never should be, such as operator&&, operator|| and operator,).

What is unusual is how an overloaded operator-> is interpreted. First, although a->b looks like -> is a binary operator, when you overload it in C++, it's treated as a unary operator, so the correct signature is T::operator(), not T::operator(U) or something on that order.

The result is interpreted somewhat unusually as well. Assuming foo is an object of some type that overloads operator->, foo->bar is interpreted as meaning (f.operator->())->bar. That, in turn, restricts the return type of an overloaded operator->. Specifically, it must return either an instance of another class that also overloads operator-> (or a reference to such an object) or else it must return a pointer.

In the former case, a simple-looking foo->bar could actually mean "chasing" through an entire (arbitrarily long) chain of instances of objects, each of which overloads operator->, until one is finally reached that can refer to a member named bar. For an (admittedly extreme) example, consider this:

#include <iostream>

class int_proxy {
    int val;
public:
    int_proxy(): val(0) {}
    int_proxy &operator=(int n) { 
        std::cout<<"int_proxy::operator= called\n";
        val=n; 
        return *this; 
    }
};

struct fubar {
    int_proxy bar;
} instance;

struct h {
    fubar *operator->() {
        std::cout<<"used h::operator->\n";
        return &instance;
    }
};

struct g {
    h operator->() {
        std::cout<<"used g::operator->\n";
        return h();   
    }
};

struct f {
    g operator->() { 
        std::cout<<"Used f::operator->\n";
        return g();
    }
};

int main() {
    f foo;

    foo->bar=1;
}

Even though foo->bar=1; looks like a simple assignment to a member via a pointer, this program actually produces the following output:

Used f::operator->
used g::operator->
used h::operator->
int_proxy::operator= called

Clearly, in this case foo->bar is not (even close to) equivalent to a simple (*foo).bar. As is obvious from the output, the compiler generates "hidden" code to walk through the whole series of overloaded -> operators in various classes to get from foo to (a pointer to) something that has a member named bar (which in this case is also a type that overloads operator=, so we can see output from the assignment as well).

Upvotes: 8

dead programmer
dead programmer

Reputation: 4375

Good Question,

Dot(.) this operator is used for accessing the member function or sometime the data member of a class or structure using instance variable of that class/Structure.

object.function(); 
object.dataMember; //not a standard for class.

arrow(->) this operator is used for accessing the member function or sometime the data member of a class or structure but using pointer of that class/Structure.

ptr->function();
ptr->datamember; //not a standard for class.

Upvotes: 3

dmastylo
dmastylo

Reputation: 881

The -> operator is a way of calling a member function of the pointer that is being dereferenced. It can also be written as (*pter).printCap(). C++ is difficult to learn without a class or book so I recommend getting one, it'll be a great investement!

Upvotes: 2

Related Questions