why does this work ? (operator overloading)

P

PKH

This is a part of an autopointer template i'm using. I originally had a
Get() member that returned the pointer, but thought it would nice to be able
to use the -> operator.
The question is why does the following line work, and call
cAP.m_pcPointer->Testing() ?

cAP->Testing(); // ???

cAP-> returns a CTest*, so it looks to me like the line reads
cAP.m_pcPointer <whitespace> Testing(), but it actually does
cAP.m_pcPointer->Testing(). I thought maybe it would be called with a bad
this-pointer, but it's the this-pointer is correct inside Testing(). What am
I not seeing here ?


template <class T> class TAutoPointer
{
private:
T
m_pcPointer;

public:
TAutoPointer(T t) : m_pcPointer(t) {}
~TAutoPointer(){if (m_pcPointer) delete m_pcPointer;}

T& operator -> ()
{
return m_pcPointer;
}
};


class CTest
{
int
m_nTest;

public:
CTest() : m_nTest(123) {}

void Testing()
{
int
i = 0;
}
};

typedef TAutoPointer < CTest* > CTestAutoPtr;



int main(int argc, char* argv[])
{
CTestAutoPtr
cAP(new CTest);


cAP->Testing();

return 0;
}
 
R

Rolf Magnus

PKH said:
This is a part of an autopointer template i'm using. I originally had a
Get() member that returned the pointer, but thought it would nice to be
able to use the -> operator.
The question is why does the following line work, and call
cAP.m_pcPointer->Testing() ?

cAP->Testing(); // ???

cAP-> returns a CTest*, so it looks to me like the line reads
cAP.m_pcPointer <whitespace> Testing(), but it actually does
cAP.m_pcPointer->Testing(). I thought maybe it would be called with a bad
this-pointer, but it's the this-pointer is correct inside Testing(). What
am I not seeing here ?

You're not making a difference between the operator-> and the x->y
statement. cAp->Testing() will first execute operator-> for cAp and then
call Testing on the returned pointer.
If you want to do that explicitly, you can write:

cAP.operator->()->Testing();
 
G

Georg Krichel

PKH said:
This is a part of an autopointer template i'm using. I originally had a
Get() member that returned the pointer, but thought it would nice to be able
to use the -> operator.
The question is why does the following line work, and call
cAP.m_pcPointer->Testing() ?

cAP->Testing(); // ???

cAP-> returns a CTest*, so it looks to me like the line reads
cAP.m_pcPointer <whitespace> Testing(), but it actually does
cAP.m_pcPointer->Testing(). I thought maybe it would be called with a bad
this-pointer, but it's the this-pointer is correct inside Testing(). What am
I not seeing here ?


template <class T> class TAutoPointer
{
private:
T
m_pcPointer;

public:
TAutoPointer(T t) : m_pcPointer(t) {}
~TAutoPointer(){if (m_pcPointer) delete m_pcPointer;}

T& operator -> ()
{
return m_pcPointer;
}
};


class CTest
{
int
m_nTest;

public:
CTest() : m_nTest(123) {}

void Testing()
{
int
i = 0;
}
};

typedef TAutoPointer < CTest* > CTestAutoPtr;



int main(int argc, char* argv[])
{
CTestAutoPtr
cAP(new CTest);


cAP->Testing();

return 0;
}

The magic of operator -> !

operator -> is an unary (!) operator, and it's overloading has a very
special meaning:
an overloaded operator -> must return something to that another operator ->
can be applied.

An example for illustration:

struct S { int i; }
S s = { 4711 };

class X
{
public:
S* operator->() { return &s; }
};

class Y
{
public:
X operator->() { return X(); }
};

class Z
{
public:
Y operator->() { return Y(); }
};

Z z;
int v = z->i;

Here, v will be initialized with 4711!
Why? "z->" results to an object of type Y, which has an operator->. This
operator results to an X with an operator-> resulting an pointer S*. To this
pointer the simple C++ operator-> for pointers can be applied and gives the
value of s.i .
So
int v = z->i;
will be compiled as
int v = z.Z::eek:perator->().Y::eek:perator->().X::eek:perator->()->i;

In your code cAP-> results to an CTest*& to which the operator -> for
pointers will be applied and call CTest::Testing().

Greeting from Cologne, Germany
Georg
 
K

Karl Heinz Buchegger

PKH said:
[snip]
The question is why does the following line work, and call
cAP.m_pcPointer->Testing() ?

cAP->Testing(); // ???

cAP-> returns a CTest*, so it looks to me like the line reads
cAP.m_pcPointer <whitespace> Testing(), but it actually does
cAP.m_pcPointer->Testing(). I thought maybe it would be called with a bad
this-pointer, but it's the this-pointer is correct inside Testing(). What am
I not seeing here ?

The returned pointer from operator-> is automatically dereferenced
for you in any case. So operator-> is a little bit special, as
it doesn't return the final 'result' of the operation, but it's
result is used for an additional operation. Same with operator*()

Without that behaviour it would not be possible to use those
operators without major syntax changes.
 
P

PKH

Ok, thanks for clearing that up. I didn't know the operator worked like
that.

PKH

Georg Krichel said:
PKH said:
This is a part of an autopointer template i'm using. I originally had a
Get() member that returned the pointer, but thought it would nice to be able
to use the -> operator.
The question is why does the following line work, and call
cAP.m_pcPointer->Testing() ?

cAP->Testing(); // ???

cAP-> returns a CTest*, so it looks to me like the line reads
cAP.m_pcPointer <whitespace> Testing(), but it actually does
cAP.m_pcPointer->Testing(). I thought maybe it would be called with a
bad
this-pointer, but it's the this-pointer is correct inside Testing(). What am
I not seeing here ?


template <class T> class TAutoPointer
{
private:
T
m_pcPointer;

public:
TAutoPointer(T t) : m_pcPointer(t) {}
~TAutoPointer(){if (m_pcPointer) delete m_pcPointer;}

T& operator -> ()
{
return m_pcPointer;
}
};


class CTest
{
int
m_nTest;

public:
CTest() : m_nTest(123) {}

void Testing()
{
int
i = 0;
}
};

typedef TAutoPointer < CTest* > CTestAutoPtr;



int main(int argc, char* argv[])
{
CTestAutoPtr
cAP(new CTest);


cAP->Testing();

return 0;
}

The magic of operator -> !

operator -> is an unary (!) operator, and it's overloading has a very
special meaning:
an overloaded operator -> must return something to that another
operator ->
can be applied.

An example for illustration:

struct S { int i; }
S s = { 4711 };

class X
{
public:
S* operator->() { return &s; }
};

class Y
{
public:
X operator->() { return X(); }
};

class Z
{
public:
Y operator->() { return Y(); }
};

Z z;
int v = z->i;

Here, v will be initialized with 4711!
Why? "z->" results to an object of type Y, which has an operator->. This
operator results to an X with an operator-> resulting an pointer S*. To
this
pointer the simple C++ operator-> for pointers can be applied and gives
the
value of s.i .
So
int v = z->i;
will be compiled as
int v = z.Z::eek:perator->().Y::eek:perator->().X::eek:perator->()->i;

In your code cAP-> results to an CTest*& to which the operator -> for
pointers will be applied and call CTest::Testing().

Greeting from Cologne, Germany
Georg
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,470
Messages
2,571,809
Members
48,797
Latest member
PeterSimpson
Top