6

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.

TRiG
  • 10,148
  • 7
  • 57
  • 107
Erasmus
  • 427
  • 2
  • 10
  • 23
  • 1
    The arrow is just the pointer's version of the dot. Sometimes you'll need pointers, so that's when you use it. Most of the time, a smart pointer would better suit you than a raw one, though. – chris Oct 23 '12 at 03:55
  • 1
    This provides some additional insight. http://stackoverflow.com/questions/7058339/c-when-to-use-references-vs-pointers – JDischler Oct 23 '12 at 03:59
  • 1
    From your question it seems clear that you know the answer already: Use the arrow when dealing with pointers to objects, rather than objects or references to objects. Perhaps the real questions is: When to use a pointer? There are questions about that already, e.g. http://stackoverflow.com/questions/162941/why-use-pointers and http://stackoverflow.com/questions/7058339/c-when-to-use-references-vs-pointers. – jogojapan Oct 23 '12 at 04:02

3 Answers3

7

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).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Great addition here. Between your answer and YS's answer, nearly everyone should have what they need. Now if we could get search engines to return results for symbols like '->'... – jww Jan 15 '14 at 02:26
  • @noloader: You might want to take a look at [SymbolHound](http://symbolhound.com/). – Jerry Coffin Jan 15 '14 at 04:17
3

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.
dead programmer
  • 4,223
  • 9
  • 46
  • 77
2

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!

dmastylo
  • 881
  • 7
  • 11