using operator overloding with template

T

Tony Johansson

Hello Experts!

I have one class template here called Handle and one concrete class called
Point.
At the bottom is the main program and the class template definitions for
Handle.
This program works fine but there are two thing that I
don't understand completely and that is these two operator that exist in the
class template Handle.
Body* operator->()
{ return bridge; }

Body& operator*()
{ return *bridge; }

How can it be possible to use this line cout << hp1->getX() << endl;
when hp1 is not a pointer. I instansiate this hp1 in main that exist at the
bottom.

And the same here how can it be possible to dereference object hp1
when hp1 is not a pointer.
Point b = *hp1;


The second question is the operator->() returns a pointer so the statement
hp1-> will return a pointer to
Body by calling the operator->() how is it then possible to call getX(). If
I substitute this it's look like.
hp1.operator->()getX
Note you have no -> before getX. Because this program works there must exist
a -> before getX but I can't understand how these two characters -> can be
placed there.



********************
class definition for Handle
********************
template <typename Body>
class Handle
{
public:
explicit Handle(Body* b = 0) : bridge(b), counter(new int(1))
{ }

Handle(const Handle<Body>& h) :counter(h.counter)
{ (*counter)++; }

~Handle()
{
if (--(*counter) == 0)
{
delete counter;
delete bridge;
}
}

Handle& operator=(const Handle<Body>& rhs)
{
if (this == &rhs || bridge == rhs.bridge)
return *this;

if (--(*counter) == 0)
{
delete counter;
delete bridge;
}

bridge = rhs.bridge;
counter = rhs.counter;
(*counter)++;
return *this;
}

Body* operator->()
{ return bridge; }

Body& operator*()
{ return *bridge; }

private:
Body* bridge;
int* counter;
};

class Point
{
public:
Point(double d1=0, double d2=0) : x(d1), y(d2) {}
virtual ~Point() {}

double getX()
{ return x; }

double getY()
{ return y; }

void setX(double d)
{ x = d; }

void setY(double d)
{ y = d; }
private:
double x;
double y;
};

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

int main()
{
Handle<Point> hp1(new Point(1,2));
cout << hp1->getX() << endl;
Point b = *hp1;

Handle<Point> hp2(hp1);
Handle<Point> hp3(new Point(3,4));
hp3 = hp2;
cout << hp2->getY() << " " << hp3->getY() << endl;
return 0;
}

Many thanks

//Tony
 
V

Victor Bazarov

Tony said:
I have one class template here called Handle and one concrete class called
Point.
At the bottom is the main program and the class template definitions for
Handle.
This program works fine but there are two thing that I
don't understand completely and that is these two operator that exist in the
class template Handle.
Body* operator->()
{ return bridge; }

Body& operator*()
{ return *bridge; }

How can it be possible to use this line cout << hp1->getX() << endl;
when hp1 is not a pointer. I instansiate this hp1 in main that exist at the
bottom.

And the same here how can it be possible to dereference object hp1
when hp1 is not a pointer.
Point b = *hp1;
[...]

That's just the convention the language has. If a type overloads the
operator ->, then the expression object_of_that_type->something resolves
into

(object_of_that_type.operator->)->something

As to the dereference operator, think of it as if it were the unary +,
there is no difference in syntax.

V
 
D

Dan Cernat

Tony said:
Hello Experts!

I have one class template here called Handle and one concrete class called
Point.
At the bottom is the main program and the class template definitions for
Handle.
This program works fine but there are two thing that I
don't understand completely and that is these two operator that exist in the
class template Handle.
Body* operator->()
{ return bridge; }

Body& operator*()
{ return *bridge; }

How can it be possible to use this line cout << hp1->getX() << endl;
when hp1 is not a pointer. I instansiate this hp1 in main that exist at the
bottom.
it is using the operator->() method you provided. Note that you didn't
override the -> operator for pointers to Handle objects but for objects
of type Handle. One cannot override the -> operator for pointers to
objects.
And the same here how can it be possible to dereference object hp1
when hp1 is not a pointer.
Point b = *hp1;
same goes here. You override operators for objects not for pointers to
objects
The second question is the operator->() returns a pointer so the statement
hp1-> will return a pointer to
Body by calling the operator->() how is it then possible to call getX(). If
I substitute this it's look like.
hp1.operator->()getX
Note you have no -> before getX. Because this program works there must exist
a -> before getX but I can't understand how these two characters -> can be
placed there.

operator->() is special. The compiler will insert that arrow (->)
before getX so the statement will look like

hp1.operator->()->getX

As I said, the operator is special. It applies itself recursively. That
is, if the operator->() returns an object, then the operator->() will
be called for that object and so on until the return value is a
pointer. Then, the regular operator -> is applied to that pointer. See
the code below:

#include <iostream>

// provides the getX method
class A
{
int m_x;
public:
int getX()
{
return m_x;
}

A(int val) : m_x(val)
{
}
};

class B
{
A m_a;
public:
B(int val) : m_a(val)
{
}

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

class C
{
B m_b;
public:
C(int val) : m_b(val)
{
}

// note that it returns an object (not a pointer)
B operator->()
{
return m_b;
}
};



int main()
{
C c(100);
// check out the statement below
std::cout << c->getX() << std::endl;

return 0;
}
Many thanks

//Tony

dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top