How to add standard and user defined objects? - c++

Hi I am trying to do operator overloading for +(addition) operator to add my user defined datatype objects .
Following is the code for that.
#include <iostream>
using namespace std;
class complex {
int i;
double f;
public:
complex(int ii=0,double ff=0){
i = ii;
f = ff;
}
complex operator+(complex object) {
complex result;
result.i = this->i + object.i;
result.f = this->f + object.f;
return result;
}
void display() {
cout << i <<"\t"<< f;
cout << endl;
}
};
int main(){
complex obj1(1,1.1),obj2(2,2.2),obj3;
int i(5);
obj3 = obj1 + obj2;
obj3.display();
obj3 = obj3 + i;
obj3.display();
obj3 = i + obj3;//generates me compiler error
obj3.display();
return 0;
}
I have learnt that when I do obj1 + obj2,it is expanded by the compiler as obj1.operator+(obj2);
So that part of code works fine.
But when I do add an int and complex ,I think it get expanded as i.operator(obj1).
So it gives me compiler errors.
Should I define operator+ function in int class or how to solve this?
Please suggest,
Thank you,

You will have to provide an overloaded version of + which takes int and class complex object as input parameters. This function should be a non member function.
complex operator+(int i, complex object)
Note that additionally, if you want to access protected or private members inside this overloaded function then it will have to be made friend of your complex class.
This is a peculiar example of the strength of free functions used for operator overloading as against member function operator overloads.

This is the reason why the operator+ is usually defined as a free function: instead of having complex complex::operator+(complex object), you could (should) define a free function
complex operator+(const & complex lhs, const & complex rhs)
{
return complex(lhs.i + rhs.i, lhs.j + rhs.j);
// You will need some way to access i and j, either by making this function
// a friend of complex or by providing getters
}
This way, the line obj3 = i + obj3 will be equivalent to operator+(i, obj3); since an integer can be converted to a complex thanks to the constructor you wrote, the call will succeed and be equivalent to this one: operator+(complex(i), obj3).
As a rule of thumb, you should prefer free functions over member functions to overload binary operators when the left hand side and the right hand size have equal importance. This way, you know that if a op b works then b op a will work too.
On a sidenote, you should also prefer passing your parameters as reference-to-const, and mark your member functions as const when they are (like operator+ and display in your sample).

Define a function outside any class:
complex operator + (int lhs, complex rhs) { /* ... */ }
Make sure the compiler can see it, and you can add ints to complexes to your heart's content. You probably also want one with the parameters the other way around.

Related

Error while passing argument number in operator overloading?

I want to add two objects. When I pass two arguments in operator overloading it gives me error that there must be zero or one argument. I want to know that why I can't pass two objects as argument in order to add them.
class Rectangle
{
private:
int L;
int B;
public:
Rectangle() //default constructor
{
L = 2;
B = 2;
}
Rectangle(int l,int b) //parametrized constructor
{
L = l;
B = b;
}
Rectangle operator+ (Rectangle obj1,Rectangle obj2) //operator overloading
{
Rectangle obj3
obj3.L = obj1.L + obj2.L;
obj3.B = obj1.B + obj2.B;
return obj3
}
void Display()
{
cout<< "length is " << L <<endl;
cout<< "breadth is " << B <<endl;
}
};
int main()
{
Rectangle R1;
R1.Display();
Rectangle R2(5,3);
R2.Display();
//Rectangle R3;
//R3 = R1 + R2;
//R3.Display();
return 0;
}
A binary operator like addition requires 2 operands. Overloading such an operator would mean that the overloaded method will work on 2 operands as well. The reason you need to provide only 1 parameter is in which scope you declared your overload, namely within Rectangle class. Basically, since that overload function is a member of Rectangle class, the left-hand side operator will be considered as this, the instance of the object itself. As a result, you merely need to provide the right-hand side operator as the parameter.
An alternative way to declare the functionality you have in mind would be overloading the addition operator outside the scope of Rectangle class. Then, you would indeed have to provide both the operands. But in that case you should mind the encapsulation. (i.e. find out a way to construct the resulting Rectangle instance without accessing only the public members of the Rectangle class) This consideration of encapsulation is one of the reasons why operators are commonly implemented as member functions, despite the parameter passing seeming counter intuitive to people who recently began learning an object oriented programming language.
This, however is fairly basic information on operator overloading, and I believe you should read up more on overloading, specifically on how overloading operators via member functions affect the overloading process.
In the code above, operator+ is a member function. In its declaration it has two named arguments; it also has an implied this pointer, because it's a member function. That makes three arguments. The compiler is saying that operator+ should take exactly one or exactly two arguments. That's because there are two possible forms of +, one unary and one binary. That is, you can write +2, which uses unary plus, or you can write 2+2, which uses binary plus.
This can be fixed in two different ways. One is to make it a static member function; that doesn't take a this pointer, so a static operator+ with two named arguments in fact takes two arguments.
A better approach is to make it a non-member function. Move it out of the class definition, and fix the error that comes from assigning to the data members of obj3. Rectangle has a constructor that takes two arguments; use it. You'll also have to add a way of getting the two values out, which you need regardless of how you implement this particular function. So it looks like this:
Rectangle operator+(Rectangle obj1, Rectangle obj2) {
Rectangle obj3(obj1.getL() + obj2.getL(), obj1.getR() + obj2.getR());
return obj3;
}
A more general approach is to provide operator+=(Rectangle obj), as a member function:
void operator+=(Rectangle obj) {
L += obj.L;
R += obj.R;
}
and use that to implement the non-member operator+:
Rectangle operator+(Rectangle obj1, Rectangle obj2) {
obj1 += obj2;
return obj1;
}

Can someone point out why my variables are unidentified and why I can't overload my operators

I don't dabble in C++ very often, but I'm learning about data structures and the book uses c++ as it language. I'm currently going over setting up classes.
My issues are:
Visual Studio 2012 is barking about unidentified variables. I have the variables declared in my header, so I'm not quite sure why I'm having the issue.
I'm trying to overload the addition and multiplication operators (as non-member functions) but it is still trying to use it as if I'm only allowed to have one parameter for the overload.
Here is some code for what I'm doing:
1. Unidentified variables
/* Quadratic.h */
#include <iostream>
using namespace std;
class Quadratic
{
public:
// constructors
Quadratic::Quadratic()
// accessors
Quadratic::getA();
Quadratic::getB();
Quadratic::getC();
// mutators
Quadratic::setCoefficients(float coA, float coB, float coC);
private:
float a, b, c, x;
};
Quadratic.cpp:
/* Quadratic.cpp */
#include <iostream>
#include "Quadratic.h"
using namespace std;
class Quadratic
{
// Default constructor
Quadratic::Quadratic()
{
a = 0; // Visual Studio is complaining about a, b, & c
b = 0;
c = 0;
}
/* Mutators */
void Quadratic::setCoefficients(float coA, float coB, float coC)
{
a = coA;
b = coB;
c = coC;
}
/* Accessors */
float Quadratic::getA() const {
return a;
}
float Quadratic::getB() const {
return b;
}
float Quadratic::getC() const {
return c;
}
};
So that is what the first issue is about. I'm not quite sure why it isn't able to find those variables. Can someone point out what I'm doing wrong?
2. Overloading Operator (mismatch on the parameters)
/* Quadratic.h */
/* Overloading Operators */
Quadratic & operator+(const Quadratic & q1, const Quadratic & q2);
Quadratic & operator*(double r, const Quadratic & q);
It is simply telling me that I have too many parameters. I'm thinking it is expecting to do something like q1.operater+(q2) where as I'm wanting to be able to do something like q3 = q1 + q2
Any pointers would be great for fixing these small issues.
Edit
Compiler errors as requested:
error C2804: binary 'operator +' has too many parameters
error C2804: binary 'operator *' has too many parameters
Basically what I mentioned above, perhaps I wasn't clear about it though.
Edit 2
Not sure why it was downvoted, but if you're going to downvote it, at least state why... If it was because the question was novice? Because the question was poorly worded or explained, or just because your ego is too high? No need to put someone down when they are attempting to learn something new.
Other than that, thank you legend2k, john, steve, salda and basile for all taking the time to help me out. I really do appreciate it. C++ is a lot more hands on than Java.
In your Quadratic.cpp you need to remove the line:
class Quadratic
{
As this is hiding your definition of Quadratic in the header file. However, this is hiding errors in your header file. In the .h file you must specify the return types of the methods and you do not need to qualify the method names with Quadratic. To fix the operator overloading error make sure that they are declared outside of the class declaration in your header file.
class Quadratic {
//...
// accessors
float getA() const;
float getB() const;
float getC() const;
// mutators
void setCoefficients(float coA, float coB, float coC);
// rest of class definition as in question...
}; // end of class declaration
Quadratic & operator+(const Quadratic & q1, const Quadratic & q2);
Quadratic & operator*(double r, const Quadratic & q);
Overloading operators can cause subtle bugs. I strongly urge you to read this page to avoid the common pitfalls:
Operator overloading
Looks like you are re declaring your whole class. In C++, you say class once to declare the interface (usually in the h file), and then go about defining the methods (usually in the cpp file). By saying class in the two files you are re declaring the class instead of defining the implementation.
Also, you don't need to say Quadratic:: inside the class declaration, since the class keyword makes it where anything you declare inside it is by definition inside the class scope. In contrast, when you write your implementation, you do need to prepend Quadratic:: because you are no longer inside the class scope.
Last, you also need not "use" namespace std twice. It's enough to put it in the h file before the class declaration; it'll also be accessible from the class implementation in the cpp file because the cpp file includes the h file.
Move the operator+ and operator* functions outside of the class as John suggested. However, you've to make those functions friends of the class as you need access to the private variables of the objects.
Additionally, you've declared the operator functions as returning references, but for the syntax you need q3 = q1 + q2;, you've to return by value after constructing a new object. So after removing the current operator+ and operator* functions, you've to do
class Quadratic
{
. . .
friend Quadratic operator+ (const Quadratic &lhs, const Quadratic &rhs);
friend Quadratic operator+ (double scalar, const Quadratic &rhs);
}
Quadratic operator+ (const Quadratic &lhs, const Quadratic &rhs)
{
Quadratic result;
result.setCoefficients(lhs.a + rhs.a, lhs.b + rhs.b, lhs.c + rhs.c);
return result;
}
If you made your constructor like this
Quadratic::Quadratic(float coA = 0.f, float coB = 0.f, float coC = 0.f) :
a(coA),
b(coB),
c(coC),
x()
{
}
i.e. with default arguments, you can write the operator function in a single line:
Quadratic operator+ (const Quadratic &lhs, const Quadratic &rhs)
{
return Quadratic(lhs.a + rhs.a, lhs.b + rhs.b, lhs.c + rhs.c);
}
This will facilitates return value optimization (RVO) which will avoid copies. Also in constructors using initialization lists than member assignment is better.
The usual way is to initialize member variables (i.e. fields) in the constructor before its body:
Quadratic::Quadratic() : a(0), b(0), c(0), x(0) {};
Then I would believe the compiler would consider the fields as initialized.
(at least GCC does).
And you could declare some operators inside the class, see here:
class Quadratic {
Quadratic & operator += (const Quadratic&right);
You could declare it outside of the class, e.g.
Quadratic operator + (const Quadratic& left, const Quadratic& right);
As others told you, you probably want to return a value, not a reference.
notice that *this is the left operand, which you should usually return.
BTW, please show the exact error messages you have got, and their precise location.

How to overload an operator with multiple parameters like a + b + c?

I can operate class+class (for example I can do date+date), but can anyone explain how can I do class+class+class please? C++ does not let me define an operator with 2 parameters.
That's because there is no such operator in general.
a + b + c is (a + b) + c. First a + b, then the results
of that added to c.
EDIT:
If the objects in question are extremely big, so that creating
the temporaries in an expression like a + b + c is too
expensive, you can google for template expressions; the basic
idea is that operator+ doesn't do anything but return an
expression node, which can be evaluated later, as part of the
full expression.
By making them friends of the class, you would make sure they are binary operators, and define them separately, like so:
class someclass
{
int a;
public:
someclass();
...
friend someclass operator+(const someclass & lhs, const someclass & rhs);
};
someclass operator+(const someclass &lhs, const someclass &rhs)
{
someclass a = lhs;
a.a = a.a + rhs.a;
return a;
}
you will, of course need to define a copy constructor (someclass(const someclass & old);) and the other functions of the class, but this method has always worked for me, and it was how I was taught in college.
There are two ways you can approach this. The normal way with operators is, you just create a normal two operand operator, and then chain the calls together. For example a + b + c + d => operator+(operator+(operator+(a + b), c), d).
Alternately, create your own named function or member that provides a multi-parameter version, using the name to accurately describe what it does.
I suggest reading http://www.cs.rit.edu/~mjh/docs/c++-faq/operator-overloading.html
To the best of my understanding you do not need 2 parameters here. Your overload needs to return an object which the result of your operation. In this case your example class+class+class can actually be written as class+(class+class) so that (class+class) is processed first and then the result of that is added to the third class.
You are allowed to use arithmetic operators with two parameters. For example:
//References are used here as arguments.
Cents operator+(const Cents &c1, const Cents &c2)
{
// use the Cents constructor and operator+(int, int)
return Cents(c1.m_nCents + c2.m_nCents);
}
(Source: http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/)
Note: you need to declare the operator "function" as friend in class definition if you need to use private members of your class in it.
If you then return a class type same with those given as arguments (objects or references of them as here), you can do class + class + class..., assuming that each operator+ call is between 2 arguments, and the result is added to the third one invoking again the operator+ "function" etc.

Operator override - when to use friend?

I'm wondering why the () operator override can't be "friend" (and so it needs a "this" additional parameter) while the + operator needs to be friend like in the following example:
class fnobj
{
int operator()(int i);
friend int operator+(fnobj& e);
};
int fnobj::operator()(int i)
{
}
int operator+(fnobj& e)
{
}
I understood that the + operator needs to be friend to avoid the "additional" extra this parameter, but why is that the operator() doesn't need it?
You have overloaded the unary plus operator. And you probably didn't want to do that. It does not add two objects, it describes how to interpret a single object when a + appears before it, the same as int x = +10 would be interpreted. (It's interpreted the same as int x = 10)
For the addition operator, it is not correct that "the + operator needs to be friend".
Here are two ways to add two fnobj objects:
int operator+(fnobj& e);
friend int operator+(fnobj& left, fnobj& right);
In the first form, this is presumed to be the object to the left of the +. So both forms effectively take two parameters.
So to answer your question, instead of thinking that "operator() doesn't need friend", consider it as "operator() requires this" Or better still, "Treating an object as a function requires an object".
You didn't understand this correctly (and aren't using it correctly as well).
There are two ways in C++ to define a binary operator for a class, either as a member function
class A
{
public:
int operator+ (A const& other);
};
or as a free function
class A {};
int operator+ (A const& lhs, A const& rhs);
What you are currently mixing up is that you can declare and define this free function in the class scope as friend, which will allow the function to use private members of the class (which is not allowed in general for free functions).

Deriving from a class with operator overloading

I want to create a collection of classes that behave like math vectors, so that multiplying an object by a scalar multiplies each field by that ammount, etc. The thing is that I want the fields to have actual names, instead of being treated as an index.
My original idea to implement this was creating a base class Rn with the overloads and then create derived classes with the pretty names. Something like this:
#include <iostream>
#include <algorithm>
using namespace std;
template<int N, class X=double>
struct Base{
X xs[N];
Base(){};
Base(X *data){
copy(data, data+N, xs);
}
Base operator*= (double d){
for(int i=0; i<N; i++){
xs[i] *= d;
}
return *this;
}
Base operator* (double d){
Base answer = *this;
answer *= d;
return answer;
}
//also operators for +=, +, multiplication from left, maybe [] too
};
struct Derived : public Base<2>{
Derived(double a, double b){
foo() = a;
bar() = b;
}
double &foo(){ return xs[0]; }
double &bar(){ return xs[1]; }
};
int main()
{
//this is OK:
double data[2] = {0.0, 2.0};
Base<2> b(data);
b = b*17.0;
cout << b.xs[0] << endl;
//I can't do this:
Derived x(0.0, 2.0);
x = x*17.0;
cout << x.foo() << endl;
return 0;
}
I get a compiler error whenever I try to use of of the operators that requires copying.
gcc gave me the following compiler error:
teste.cpp: In function ‘int main()’:
teste.cpp:52: error: no match for ‘operator=’ in ‘x = x.Derived::<anonymous>.Base<N, X>::operator* [with int N = 2, X = double](1.7e+1)’
teste.cpp:31: note: candidates are: Derived& Derived::operator=(const Derived&)
I think the problem is that the overloading functions deal with Base objects that can't be converted to Derived ones, so I can't use them in the derived class. However, I can't come up with a solution. Is there a way around this or should I use a totally different approach?
Bonus question: is there some way that I can use std::valarray to keep from having to type lots and lots of operator overloads?
Your Base operators (* in this case) can accept Derived object, but they return a Base, which can't be used as a right-hand operand in Derived default assignment operator. Easiest way to fix this is just add an assignment operator to Derive that will take a Base:
Derived& operator= (const Base<2>& other)
You will have to add it to any derived class, but the implementation is rather straightforward (you can have a void CopyOtherBase function in Base that will do the copy, and have all operator= call it and return *this).
I'll only address the technical difficulty, not whether this is a good idea or not.
The problem is that the result of operator* of Derived is a Base, and operator= of Derived (which is a default operator=) doesn't know how to "eat" a Base.
A simple solution is to create a constructor of Derived that gets a Base, and does whatever is needed to initialize itself correctly. This would allow an on-the-fly conversion of a Base to a Derived - and would work for all other operators of Derived that expect a Base.
Something along the lines of -
Derived(const Base<2>& B) : Base<2>( B )
{
}
I think you're going to be much better off using an enum or static constants to name your fields
e.g., static const int FIELD_NAME = 0;
Static const int FIELD_NAME2 = 1;
than doing this as different types (templates). Then you can go for std::valarray or boost::ublas::vector/matrix types to leverage existing code & get quality performance vector operations to boot.
Template metaprogramming had an interesting idea on solving just this sort of issue with math vectors, but perhaps doesn't solve your issue of naming the parts.
David Abrahams, Aleksey Gurtovoy: C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond, Addison-Wesley, ISBN 0-321-22725-5
According to MSDN,
All overloaded operators except
assignment (operator=) are inherited
by derived classes.
Could this be your problem?