4

When I looked up books and stack overflow article on operator overloading, I found the following:

When an overloaded operator is a member function, this is bound to the left-hand operand. Member operator functions have one less (explicit) parameter than the number of operands.

(Addison Wesley, C++ Primer)

So my question is, since the * (dereference) operator does not have any left operand, how does it get its parameter (which is the object itself or this)?

Community
  • 1
  • 1
sushrut619
  • 843
  • 8
  • 20
  • I did not find any reliable source which states that an overloaded unary operator member function would take right hand operand as an implicit argument if required. – sushrut619 Nov 02 '16 at 01:13
  • It's an unary operator, it operates on the value follows it – Danh Nov 02 '16 at 01:14
  • As an added question would there be any difference in how the overloaded * operator is used if it is defined as a non-member function vs a member function ? – sushrut619 Nov 02 '16 at 01:15

3 Answers3

3

For all prefix unary operator, it operates on the operand that follows it.

As an added question would there be any difference in how the overloaded * operator is used if it is defined as a non-member function vs a member function

For the most part, no, except that non-member function can't access private member of that class and if both the member function and non-member function existed, compiler needs to use overload resolution to pick the higher rank function, if there're no better function, it's ambigious call, see ADL

For the reliable source, you can take a look at operator overloading, or, better, section 13.5.1 [over.unary] in the standard C++:

A prefix unary operator shall be implemented by a non-static member function (9.3) with no parameters or a non-member function with one parameter. Thus, for any prefix unary operator @, @x can be interpreted as either x.operator@() or operator@(x). If both forms of the operator function have been declared, the rules in 13.3.1.2 determine which, if any, interpretation is used. See 13.5.7 for an explanation of the postfix unary operators ++ and --. 2 The unary and binary forms of the same operator are considered to have the same name. [ Note: Consequently, a unary operator can hide a binary operator from an enclosing scope, and vice versa. —end note ]

For the selection if there are both member and non-member, see 13.3.1.2 [over.match.oper]

Danh
  • 5,916
  • 7
  • 30
  • 45
0

Prefix * operates on the operand that follows it.

For a user defined operator* expressed as a member function, that's the object that's referred to by a this-expression.

#include <iostream>
using namespace std;

struct S
{
    auto operator*() const -> char const* { return "Hi there!"; }
};

auto main()
    -> int
{ cout << *S() << endl; }

Result:

Hi there!
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • As an added question would there be any difference in how the overloaded * operator is used if it is defined as a non-member function vs a member function ? – sushrut619 Nov 02 '16 at 01:26
  • @sushrut619: That depends on how it is defined. To emulate a `const` member function it should take its argument by value or by reference to `const`. Otherwise it can't be called on `const` argument. – Cheers and hth. - Alf Nov 02 '16 at 01:27
0

The dereference operator works exactly the same way as an overloaded operator as it does as an ordinary operator.

int foo(int *p)
{
     return *p;
}

In the statement return *p;, the dereference operator applies to the pointer p. It is passed to it on the right side:

As an overloaded operator, it works the same way.

class bar {

     int *some_internal_ptr;

public:
     int operator*() const {
          return *some_internal_ptr;
     }

     // Other class members and methods...
};

int foo(bar p)
{
     return *p;
}

When the right-hand side of the * operator is class with an operator*` member, it gets invoked as an overloaded method of the class, no different than any other member, in order to resolve the dereference.

It is because the usage is identical is why many C++ library algorithms work equally well with either pointers or C++ library operators. For example, std::copy() could be implemented as follows (I am trimming away some irrelevant complexity that's not germane here):

template<typename iter_type>
iter_type copy(iter_type b, iter_type e, iter_type t)
{
    while (b != e)
    {
       *t=*b;
       ++t;
       ++b;
    }
    return t;
}

You can pass native pointers to std::copy, or pass classes like iterators, with overloaded * operators, and because an overloaded * operator is used with the same syntax as an ordinary * operator, the same algorithm works with the overloaded operator as well.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148