0

I have multiple errors that say either "<snippet of code> needs zero or one argument" or "<snippet of code> needs exactly one argument." For the sake of simplicity I will only post one of these sections of code from my file.h and my file.cc. I don't believe there is anything wrong with my main.cc. Also, the function must be a friend function of the class my_int, so I cannot make it a different type of function or simply use accessor functions. Any help anyone could provide would be most appreciated. Thank you!

file.cc

(friend function of my_int class):

my_int my_int::operator+(const my_int& num1, const my_int& num2) {
    my_int temp;

    temp = num1 + num2;

    return(temp);
}

file.h

(inside a class named my_int)

friend my_int operator+(const my_int& num1, const my_int& num2);
David G
  • 94,763
  • 41
  • 167
  • 253
user2905256
  • 145
  • 2
  • 12
  • for the sake of understanding, post a minimal compilable example – vsoftco Nov 28 '14 at 00:39
  • 3
    If that did work wouldn't it end up in a recursive loop and crash? – Jonathan Potter Nov 28 '14 at 00:40
  • and inside the operator+, you are using the operator itself, however this shouldn't give you a compile time error, but just a crash – vsoftco Nov 28 '14 at 00:41
  • BTW: Standard advice for overloading binary + is using the op+= member-function from a non-friend free-function. Looks like `A operator+(const A& a, const B& b) {return (A)a += b;}` Also, take a look at this overview: http://stackoverflow.com/questions/4421706/operator-overloading?rq=1 – Deduplicator Nov 28 '14 at 00:50
  • Hopefully you mean `temp.val = num1.val + num2.val` or something. – M.M Nov 28 '14 at 00:53
  • No, Mr.McNabb, I do not. I am trying to overload the operator so I can add num1 and num2 which are both of my_int type. (a class in my program) – user2905256 Nov 28 '14 at 01:00
  • Hum, yes you do, because right now you define the addition of your objects in terms of "adding your objects" which leads to infinite recursion, as pointed out earlier. – SirDarius Nov 28 '14 at 10:50

3 Answers3

1
friend my_int operator+(const my_int& num1, const my_int& num2);

means 'declare a free function which takes 2 parameters. Make it a friend so it can see my private members'

my_int my_int::operator+(const my_int& num1, const my_int& num2) {

means 'define the (illegal) member function operator+ which takes total 3 arguments.

EDIT: by request, adding some more info.

There are a number of "correct" ways to implement operators on your classes. The 'best practice' way is to implement all binary operators as free functions (operator+ as a free function is declared with 2 parameters). Operator+ should be implemented where possible in terms of operator+= (a unary operator, therefore define it in the class). It's best practice because it allows you to write overloads of operator+ that take different objects as arguments. For example:

struct X {
  explicit X(int val) : _val (val) {}

  // getter
  int value() const { return _val; }

  // this helper += operator eases our journey later on
  X& operator+=(int delta) {
    _val += delta;
    return *this;
  }

  X& operator+=(const X& r) {
    _value += r.value();
    return *this;
  }

private:
  int _val;
}

// implements X + X
X operator+(X l, const X& r)
{
  return l += r;
}

// implements X + int
X operator+(X l, int r)
{

  return l += r;
}

// implement int + X (returns an X)
X operator+(int l, X r) {
  return r += l;
  return r;
}

// later, someone else defines a Y and wants it to be addable with X, returning a Z

struct Y {
  vector<int> get_numbers() const;
}

struct Z {
  Z(vector<int> v);
}

// implement Z = X + Y;
Z operator+(const X& l, const Y& r) {
  auto v = r.get_numbers(); // vector<int> instead of auto for c++03
  v.push_back(l.value());
  return Z { std::move(v) }; // c++11
// return Z(v); // c++03
}

// also implement Z = Y + X
Z operator+(const Y&l , const X&r) {
  auto v = l.get_numbers();
  v.push_back(r.value());
  return Z { std::move(v) };
}

Note that it's possible to declare the free-function forms of binary operators as friends:

struct X {
  // this is a free function - not a class memeber, but it can see X::_value
  friend X operator+(X, const X&);
private:
  int _value;
};

// implementation
X operator+(X l, const X& r) {
  l._value += r._value;
  return l;
}

but I would argue that this style is less preferable to writing truly unbound free binary operators that are implemented in terms of unary operators (above).

It's also possible to implement binary operators as member functions - in which case they are declared and defined with one parameter (the other being implied as this):

struct X {
  X operator+(X r);
private:
  int _value;
};

X X::operator+(const X& r) {
  // l is implied as *this
  return X { _value + r._value };
}

but this is a mistake because while it allows the overload of (X + int), it does not allow overloading (int + X), for which you'd need a free function anyway.

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • To fix this, take out `my_int::` from the function definition. OP is going for a non-member friend. – M.M Nov 28 '14 at 00:52
  • I apologize, but I do not see the point you are trying to get across... could you be more specific with what I did wrong? – user2905256 Nov 28 '14 at 00:57
0

This method:

my_int my_int::operator+(const my_int& num1, const my_int& num2);

is a member function. A member function operator implicitly takes as its left parameter the object pointed to by this (which will be a my_int object). That means that your overload's parameter declaration can't contain more than one object. Change your signature to:

my_int my_int::operator+(const my_int& num2);

Now what was num1 previously is now *this.

David G
  • 94,763
  • 41
  • 167
  • 253
  • how is this a member function when it is declared as a non-member friend function in the .h file? I was told specifically to have the two parameters, so I cannot omit the num1 parameter. – user2905256 Nov 28 '14 at 00:47
  • @user2905256 This method is a member function (you even defined it using the scope resolution operator `my_int::operator+(...)`. You can make it a free function in which case you can define with two parameters. – David G Nov 28 '14 at 00:49
  • sorry for that, I didn't know what I was saying. I also do not know what you mean b a free function. If you are talking about a non-member function, I cannot do that, it had to be a friend function of the class. Basically all I am trying to do is overload the operator. – user2905256 Nov 28 '14 at 00:58
  • @user2905256 You correctly declared it as a `friend` function in your question (inside file.h). Inside file.cpp, you incorrectly used `my_int my_int::operator+(..)` to define it when all you needed was `my_int operator+(..)`. – David G Nov 28 '14 at 01:03
  • so although it is a member function, because it is a friend function, I do not need to scope resolution operator? or am I still missing the point? – user2905256 Nov 28 '14 at 01:07
  • @user2905256 Your friend declaration declares a non-member function. – David G Nov 28 '14 at 01:08
  • @user2905256 Does this make sense so far? Your `friend` declaration isn't a member function, which was why you couldn't define it like that. `friend` functions can introduce non-member functions, which you have done here, so that's why you define it as a non-member function. – David G Nov 28 '14 at 01:19
  • Ok I thought because the friend function was declared inside the class that it was a member function. So it does not need to scope resolution operator because the function is not actually a member of the function? – user2905256 Nov 28 '14 at 01:22
  • @user2905256 Yes, declaring it in the class as a `friend` doesn't make it a member of the class. – David G Nov 28 '14 at 01:23
  • Alright so i removed the scope resolution operators, and now my compiler is telling me undefined symbol _zzksomething and first referenced in /var/tmp//ccTTokbk.o – user2905256 Nov 28 '14 at 02:33
  • @user2905256 Is is still declared as a friend in the class? Did you define the function? [Read this for a possible solution.](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – David G Nov 28 '14 at 02:40
0

The operator + can be used in two kinds of expressions:

  • unary "plus" expression: +a
  • binary "plus" expression: a + b

The operator is overloadable for both kinds of expressions. Each overload must be either unary or binary. If the overload is a member function, then the implicit instance argument provides the first operand.

So you have these options:

Free functions:

  • R operator+(T a) is eligible for +a when a is convertible to T.
  • S operator+(T lhs, U rhs); is eligble for a + b when a is convertible to T and b to U.

Member functions:

 struct Foo
 {
     R operator+();        // #1
     S operator+(T rhs);   // #2
 } x;
  • Overload #1 is eligible for +x.
  • Overload #2 is eligible for x + b when b is convertible to U.
T.C.
  • 133,968
  • 17
  • 288
  • 421
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084