Thread: Overloading unary operators using pointers

  1. #1
    Registered User
    Join Date
    Aug 2009
    Posts
    140

    Overloading unary operators using pointers

    Hi

    Please take a look at this non-compilable example:

    Code:
    #include <iostream.h>
    
    class test{
    public:
    	int a;
    	friend operator++(test *b);
    };
    
    operator++(test *b)
    {
    	b->a=b->a+1;
    }
    
    int main()
    {
    	test asd;
    	asd.a=1;
            &asd++;
    
    	return 0;
    }
    This will only compile if I replace the pointer *b with a reference. In my book it says that the reason why that is the case is because "&asd++ is inherently ambigous", but explains it no further.

    What does the author mean by that?

    Best,
    Niles.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    That code should not compile even if you "replace the pointer *b with a reference". The parameter for postfix operator++ should be of type int. Then, you failed to declare the operator++ with a return type, and you made it a non-member friend function, but failed to provide it with a parameter by which the object can be passed (i.e., the parameter before the int parameter).

    By the way, <iostream.h> is pre-standard. You do not need it here, but you should otherwise use <iostream>.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    laserlight: note that this is an attempt to overload it as a free function.

    Niels: You can't overload operators for pointers, because those are built-in types. Operator++ is already defined for all pointers.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by anon
    laserlight: note that this is an attempt to overload it as a free function.
    Yes, so...?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Aug 2009
    Posts
    140
    1) "The parameter for postfix operator++ should be of type int." - Sorry, I don't know what you mean here.

    2) "Then, you failed to declare the operator++ with a return type" - I don't believe that is necessary in my case. I am using a pointer, so why return anything?

    3) "and you made it a non-member friend function, but failed to provide it with a parameter by which the object can be passed (i.e., the parameter before the int parameter)." - Sorry, I don't know what you mean here either.

    4) "By the way, <iostream.h> is pre-standard. You do not need it here, but you should otherwise use <iostream>.": Noted, thanks.


    This works:

    Code:
    #include <iostream>
    
    class test{
    public:
    	int a;
    	friend void operator++(test &b);
    };
    
    
    void operator++(test &b)
    {
    	(b.a)++;
    }
    
    int main()
    {
    	test asd;
    	asd.a=1;
    	asd++;
    
    	return 0;
    }

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Niels_M
    1) "The parameter for postfix operator++ should be of type int." - Sorry, I don't know what you mean here.
    Quote Originally Posted by Niels_M
    3) "and you made it a non-member friend function, but failed to provide it with a parameter by which the object can be passed (i.e., the parameter before the int parameter)." - Sorry, I don't know what you mean here either.
    That is, if you want to overload postfix operator++, it should either be a member function and have a dummy int parameter, or be a non-member function and have two parameters, the second of which should be the dummy int parameter. Without this int parameter, you would be overloading it as a prefix operator++.

    Quote Originally Posted by Niels_M
    2) "Then, you failed to declare the operator++ with a return type" - I don't believe that is necessary in my case. I am using a pointer, so why return anything?
    Language syntax. There are exceptions, e.g., constructors, destructors and conversion functions are not declared with a return type (though the return type is kind of explicitly stated for the conversion function anyway), but operator++ is not such a case.

    Quote Originally Posted by Niels_M
    This works:
    Not likely, unless there is some kind of language extension at work. If you change asd++; to ++asd; then it should work (or at least it should compile). Rather, if you want to overload for postfix operator++, you should write:
    Code:
    friend void operator++(test &b, int);
    and
    Code:
    void operator++(test &b, int)
    {
    By the way, is anon's guess correct? That is, are you trying to overload postfix operator++ for a pointer type? If so, then your attempt is as futile as anon stated.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Aug 2009
    Posts
    140
    Thanks for answers to 1, 2 and 3.

    If I have understood anon correctly, that is not what I am asking. What I am trying to do is to understand why I cannot do the following:

    Code:
    test_class operator++(test_class *ptr1)
    {
       ptr1->var_int++;
    }
    but I have to use this instead:

    Code:
    test_class operator++(test_class &ptr1)
    {
       ptr1.var_int++;
    }
    For now, let us not care about that test_class is, only that it contains var_int as an integer-variable. As I said before, the author of my book says that the reason the first example does not work is becayse "&test_class_object++ is inherently ambigious".

    I don't know what he means by that.


    EDIT: I hope you see this before replying, but postfix, prefix and all that is not what I am asking. Only why I cannot access test_class_object using a pointer to it in operator++, but why is has to be a reference.
    Last edited by Niels_M; 09-03-2010 at 01:11 PM.

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Yes, so...?
    Sorry, didn't properly read your reply.

    If I have understood anon correctly, that is not what I am asking. What I am trying to do is to understand why I cannot do the following
    Just as I said. You can overload operators for class-types, and can't change the way operators work for built-in types. For pointers, ++ advances the pointer by the size of the object.

    For overloaded operators, (all) operands cannot be pointers.

    The next thing you might want to try to do is:

    Code:
    int operator+(int a, int b) { return a - b; }
    No idea why the author says anything about inherent ambiguity.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Let us consider the explicit form for calling prefix operator++. That is, given an object x of some class type, this:
    Code:
    ++x;
    can be written as:
    Code:
    x.operator++();
    or:
    Code:
    operator++(x);
    Now, let us consider the explicit form for calling postfix operator++. That is, given an object y of some class type, this:
    Code:
    y++;
    can be written as:
    Code:
    y.operator++(0);
    or:
    Code:
    operator++(y, 0);
    where 0 can be replaced by some other integer value in the range of int.

    So, a non-member function with this declaration:
    Code:
    test_class operator++(test_class *ptr1);
    is a non-member function that overloads prefix operator++ to return a test_class object, with a pointer as the argument. This is simply not allowed, since operator++, in both prefix and postfix forms, already exists for pointers.

    Quote Originally Posted by Niels_M
    As I said before, the author of my book says that the reason the first example does not work is becayse "&test_class_object++ is inherently ambigious".

    I don't know what he means by that.
    I think that the author is mistaken. The first example does not work because one cannot overload operator++ for a pointer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Aug 2009
    Posts
    140
    But guys, we are not overloading ++ for a pointer, but for objects of test_class. The only thing we are doing is using a pointer as a way of identifying the test_class_object.

    But OK -- let us assume I accept your explanations, and use e.g. a reference instead (as in my example). Then I have a non-member function that overloads the prefix operator++ to return a test_class object, with a reference as the argument. This should mean that I cannot use a reference in any other prefix operator++ function for any other class. But this is not the case.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Niels_M
    But guys, we are not overloading ++ for a pointer, but for objects of test_class.
    Right.

    Quote Originally Posted by Niels_M
    The only thing we are doing is using a pointer as a way of identifying the test_class_object.
    According to the language rules, you cannot do this.

    Quote Originally Posted by Niels_M
    But OK -- let us assume I accept your explanations, and use e.g. a reference instead (as in my example). Then I have a non-member function that overloads the prefix operator++ to return a test_class object, with a reference as the argument. This should mean that I cannot use a reference in any other prefix operator++ function for any other class. But this is not the case.
    In other words, your claim that you "cannot use a reference in any other prefix operator++ function for any other class" is false.

    EDIT:
    Think about it: why should it be true? Why should having a reference parameter of type T1 for a function foo mean that you cannot overload function foo to have a reference parameter of another type T2, in general?
    Last edited by laserlight; 09-03-2010 at 01:57 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    The larch
    Join Date
    May 2006
    Posts
    3,573
    But guys, we are not overloading ++ for a pointer, but for objects of test_class. The only thing we are doing is using a pointer as a way of identifying the test_class_object.
    The argument to operator++ (as a non-member function) is the operand.

    Code:
    test operator++(test *b)
    {
    	b->a=b->a+1;
            return *b;
    }
    If this was allowed, the usage would look like
    Code:
    test* p = new test;
    ++p;  //would not increment the pointer!?
    I don't understand the second part of the question. The proper way to overload pre- and postfix increments (as non-member functions) looks like this:

    Code:
    X& operator++(X& x) //++x
    {
          x.increment();  //whatever
          return x;
    }
    
    X operator++(X& x, int)  //x++
    {
          X before_increment = x;
          ++x;
          return before_increment;
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  13. #13
    Registered User
    Join Date
    Aug 2009
    Posts
    140
    "The argument to operator++ (as a non-member function) is the operand." - In the case when overloading an operator using a member function, then the argument is not the operand?

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    A unary operator overloaded as a member would have no parameters; its operand is the current object (*this). Postfix operator++ and operator-- are exceptions in that they do have a parameter when overloaded as a member, but this parameter is just a dummy int parameter to differentiate them from prefix operator++ and operator-- respectively.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Registered User
    Join Date
    Aug 2009
    Posts
    140
    I was thinking in more general terms, i.e. also binary operators. I mean, lets say I have

    Code:
    class dummy_class{
    public:
       int a;
       void operator+(dummy_class* test);
    }
    This is totally legal, but it would not be legal if operator+ was a non-member function. My post #13 is basically just trying to figure out why (I have read about the this-pointer now).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 01-22-2002, 12:25 PM
  2. About overloading operators.
    By Dual-Catfish in forum C++ Programming
    Replies: 2
    Last Post: 12-29-2001, 07:12 PM
  3. Overloading operators...
    By Unregistered in forum C++ Programming
    Replies: 4
    Last Post: 11-21-2001, 08:24 PM
  4. Overloading Operators
    By Raven Arkadon in forum C++ Programming
    Replies: 1
    Last Post: 10-24-2001, 10:24 AM
  5. Overloading Operators
    By Strahan in forum C++ Programming
    Replies: 4
    Last Post: 09-07-2001, 11:39 AM