Could anyone explain why adding three objects like this a (a a)
causes problems while a a a
and (a a) a
does not? The Foo
class has one attribute num
. Adding two Foo
objects returns one with sum of their num
values. Here is my code.
main.cpp
#include <iostream>
#include "Foo.h"
using namespace std;
int main()
{
Foo a(4), b;
b = a a a; // works fine
cout << a.getNum() << " " << b.getNum() << endl; // outputs "4 12" as it should
b = a (a a); // this one causes an error
cout << a.getNum() << " " << b.getNum() << endl;
return 0;
}
Foo.h
#ifndef FOO_H
#define FOO_H
class Foo
{
public:
Foo();
Foo(int a);
Foo operator (Foo& other);
int getNum();
protected:
private:
int num;
};
#endif // FOO_H
Foo.cpp
Foo::Foo()
{
num = 0;
}
Foo::Foo(int a)
{
num = a;
}
Foo Foo::operator (Foo& other)
{
Foo tmp = (*this);
tmp.num = other.num;
return tmp;
}
int Foo::getNum()
{
return num;
}
The error message says error: no match for 'operator ' (operand types are 'Foo' and 'Foo')
even though the operator is overloaded for Foo
-type operands.
CodePudding user response:
All right, I got it. The only thing that I had to change was to add const
in Foo.h
Foo operator (const Foo& other);
and in Foo.cpp
Foo Foo::operator (const Foo& other)
{
Foo tmp = (*this);
tmp.num = other.num;
return tmp;
}
Thanks.
CodePudding user response:
The expression (a a)
yields a prvalue of type Foo
. The only possible reference parameter types this kind of value can be assigned to are Foo&&
or Foo const&
. The reason why (a a) a
(or the equivalent using no brackets) works is the fact that non-const functions can be invoked on prvalues.
I recommend going with the const
version in this case, but you should also mark the operator const
:
class Foo
{
...
Foo operator (Foo const& other) const;
};
Foo Foo::operator (Foo const& other) const
{
return num other.num;
}
Probably preferrable would be to implement the operator at namespace scope which would allow you to apply the implicit conversion from int
to Foo
on both sides of
:
class Foo
{
...
friend Foo operator (Foo const& s1, Foo const& s2)
{
return s1.num s2.num;
}
...
};
Using this implementation not only
Foo c = a 1;
works, but also
Foo d = 1 a;