Operator overloading example not clear - c++

I'm curently learning about operator overloading and I found this example:
#include <iostream>
using namespace std;
class MinMax
{
private:
int m_nMin; // The min value seen so far
int m_nMax; // The max value seen so far
public:
MinMax(int nMin, int nMax)
{
m_nMin = nMin;
m_nMax = nMax;
}
int GetMin() { return m_nMin; }
int GetMax() { return m_nMax; }
friend MinMax operator+(const MinMax &cM1, const MinMax &cM2);
friend MinMax operator+(const MinMax &cM, int nValue);
friend MinMax operator+(int nValue, const MinMax &cM);
};
MinMax operator+(const MinMax &cM1, const MinMax &cM2)
{
// Get the minimum value seen in cM1 and cM2
int nMin = cM1.m_nMin < cM2.m_nMin ? cM1.m_nMin : cM2.m_nMin;
// Get the maximum value seen in cM1 and cM2
int nMax = cM1.m_nMax > cM2.m_nMax ? cM1.m_nMax : cM2.m_nMax;
return MinMax(nMin, nMax);
}
MinMax operator+(const MinMax &cM, int nValue)
{
// Get the minimum value seen in cM and nValue
int nMin = cM.m_nMin < nValue ? cM.m_nMin : nValue;
// Get the maximum value seen in cM and nValue
int nMax = cM.m_nMax > nValue ? cM.m_nMax : nValue;
return MinMax(nMin, nMax);
}
MinMax operator+(int nValue, const MinMax &cM)
{
// call operator+(MinMax, nValue)
return (cM + nValue);
}
int main()
{
MinMax cM1(10, 15);
MinMax cM2(8, 11);
MinMax cM3(3, 12);
MinMax cMFinal = cM1 + cM2 + 5 + 8 + cM3 + 16;
cout << "Result: (" << cMFinal.GetMin() << ", " <<
cMFinal.GetMax() << ")" << endl;
return 0;
}
I don't understand how does the line MinMax cMFinal = cM1 + cM2 + 5 + 8 + cM3 + 16; work.
When this is calculated it becomes MinMax cMFinal = MinMax(3, 16). What happenes next? How does the compiler assign one object to another when I didn't define overloading assigment operator?

Lets say you have two MinMax objects, a and b. Then when you have a line like
MinMax c = a + b;
Then the compiler translates it to the following
MinMax c = operator+(a, b);
In other words, it's like a normal function call.
If you do multiple operations, like
MinMax d = a + b + c;
then the compiler will internally generate temporary variables and use, like
MinMax compilerGeneratedTemporary = operator+(a, b);
MinMax d = operator+(compilerGeneratedTemporary, c);
If it's the initialization you're wondering about, then it's calling the MinMax copy-constructor. When you declare and initialize an object variable at the same time then it's not an assignment, it just reuses the assignment operator.
The operator+ functions return a MinMax object, which is passed to the class copy-constructor.
If a class doesn't have a copy-constructor, the compiler will generate one for you automatically (with a few exceptions, see the reference linked below).
Read more about the copy-constructor here.

Related

C++ overload [][] for a list

I got a class Matrix with a member std::list<Element> listMatrix;. Element is a a class with 3 int members line, column, value. I save in the list, elements of a matrix that are not 0 by saving the line, column and the value of the respectively element. I want to overload the operator [][] so I can do something like Matrix a; a[2][3] = 5;. I know you can't overload [][] directly.
Do overload Element& operator()(int, int) (and the const variant) so you can write
matrix(2, 3) = 5;
If you absolutely need the [2][3] syntax, you'd need to define a proxy class so matrix[2] return a proxy value and proxy[3] return the desired reference. But it comes with a lot of problems. The basic idea would be:
class naive_matrix_2x2
{
int data[4];
struct proxy
{
naive_matrix_2x2& matrix;
int x;
int& operator[](int y) { return matrix.data[x*2+y]; }
};
public:
proxy operator[](int x) { return {*this, x}; }
};
Full demo: https://coliru.stacked-crooked.com/a/fd053610e56692f6
The list is not a suitable container for using the subscript operator because it has no direct access to its elements without moving an iterator through the list.
So the operator will be inefficient.
It is better to use the standard container std::vector that already has the subscript operator.
Nevertheless answering your question the operator can be defined the following way. You can add to the operators an exception then an index will point outside the list.
#include <iostream>
#include <list>
struct A
{
int x, y, z;
int & operator []( size_t n )
{
return n == 0 ? x : n == 1 ? y : z;
}
const int & operator []( size_t n ) const
{
return n == 0 ? x : n == 1 ? y : z;
}
};
struct B
{
std::list<A> lst;
A & operator []( size_t n )
{
auto it = std::begin( lst );
for ( ; n; n-- ) std::advance( it, 1 );
return *it;
}
const A & operator []( size_t n ) const
{
auto it = std::begin( lst );
for ( ; n; n-- ) std::advance( it, 1 );
return *it;
}
};
int main()
{
B b = { { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } } };
std::cout << b[0][0] << '\n';
std::cout << b[0][1] << '\n';
std::cout << b[0][2] << '\n';
b[2][1] += 20;
std::cout << b[2][1] << '\n';
}
The program output is
1
2
3
28

operator * overload c++

I am trying to make a program that can opearate with complex numbers. However i got stuck with operator * I cannot figure out how to make these 2 cases work:
First:
c = 10 * d;
cout << c << endl;
Second:
c = d * 10;
cout << c << endl;
This is my header:
class Complex
{
private:
double Real, Imag;
public:
Complex() : Real(), Imag()
{
}
//----------------------------------------------------------------------
Complex (double Real) //Initialization with only one variable
{
this->Real = Real;
Imag = 0;
}
//----------------------------------------------------------------------
Complex (double Real, double Imag) //Complete initialization
{
this->Real = Real;
this->Imag = Imag;
}
//----------------------------------------------------------------------
Complex & operator = (const Complex &s)
{
Real = s.Real;
Imag = s.Imag;
return *this;
}
//----------------------------------------------------------------------
Complex operator * (Complex s) // (r + i) * x
{
this->Real *= s.Real;
this->Imag *= s.Real;
return *this;
}
//----------------------------------------------------------------------
Complex & operator *= (Complex s) //Reference
{
Real *= s.Real;
Imag *= s.Imag;
return *this;
}
//----------------------------------------------------------------------
friend Complex operator * (Complex s1, Complex s2);
//----------------------------------------------------------------------
friend ostream &operator << (ostream &s, const Complex &c)
{
s << c.Real << " + " << c.Imag;
return s;
}
};
//Out of class functions
inline Complex operator * (Complex s1, Complex s2) // x * (r + i)
{
s2.Real *= s1.Real;
s2.Imag *= s1.Real;
return s2;
}
//----------------------------------------------------------------------
bool Complex::operator == (const Complex &s) const
{
return (this->Real == s.Real && this->Imag == s.Imag);
}
//----------------------------------------------------------------------
#endif /* __Complex_H__ */
My idea was to use operator inside class for second case, and outside for first case. But I got error:
error: ambiguous overload for 'operator*' in 'd * 10
How to make it clear to compiler which overload to use?
My main is:
#include <iostream>
#include "complex.h"
using namespace std;
int main()
{
Complex c, d(3, 5);
c = 10 * d;
cout << c << endl;
c = d * 10;
cout << c << endl;
}
In the first case, the friend non-class method is invoked without ambiguity because first parameter is not a Complex but can be built as such using the double to Complex constructor
In the second case, member method * and friend function can be applied, hence the error.
There's no need for a friend operator using 2 Complex objects. It's only useful when first parameter is a non-class object / a class object where you cannot set/change the behaviour of *
You'd be better off with:
friend Complex operator * (double s1, const Complex &s2);
Notes:
standard library has a very good std::complex implementation.
it would be better to use constant references rather than value parameter passing
overloading member operator*(double s1) would be interesting to avoid converting to a Complex when you want to multiply by a real value.

understanding temporary object in overloading the "/" operator

I try to understand how this line of code in blow c++ program, and my questions are
return Rational(_n * rhs._d, _d * rhs._n);
how the _n refer to the first object data member?
how the temporary object refer get the a._n?
C++ program:
#include <iostream>
class Rational {
int _n;
int _d;
public:
Rational ( int numerator = 0, int denominator = 1 ) : _n(numerator), _d(denominator) {};
Rational ( const Rational & rhs ) : _n(rhs._n), _d(rhs._d) {}; // copy constructor
inline int numerator() const { return _n; };
inline int denominator() const { return _d; };
Rational operator / ( const Rational & ) const;
};
Rational Rational::operator / ( const Rational & rhs ) const {
return Rational(_n * rhs._d, _d * rhs._n);
}
// useful for std::cout
std::ostream & operator << (std::ostream & o, const Rational & r) {
return o << r.numerator() << '/' << r.denominator();
}
int main( int argc, char ** argv ) {
using namespace std;
Rational a = 7; // 7/1
Rational b(5, 3); // 5/3
cout <<"a is : " <<a << endl;
cout << " b is : "<< b << endl;
cout << " a/b is: "<< a / b << endl;
return 0;
}
which has out put of
a is : 7/1
b is : 5/3
a/b is: 21/5
this program is simple version of this program in github
To put it in a few words, the operator / can be written like this:
class Rational
{
//...rest of the stuff:
Rational Divide( const Rational & rhs) const
{
return Rational(_n * rhs._d, _d * rhs._n);
}
};
and instead of the operator / for result = a/b you can write result = a.Divide(b)
Basically operator / behaves the same way as Divide method:
Now , let's analyze the divide method:
you have:
result = a.Divide(b); // which is the same as result = a/b in your case
and
Rational Divide( const Rational & rhs) const
{
return Rational(_n * rhs._d, _d * rhs._n);
}
rhs is the argument passed to Divide which is the variable b.
_n and _d are the members of the variable a. You can also write them like this: this->_n and this->_d. Divide is a member function so it can access _n and _d directly.
Now to simplify this even further to understand the way it works, here is another way to write this:
class Radional {/*stuff*/};
Rational Divide( const Rational & a, const Rational & b)
{
return Rational(a._n * b._d, a._d * b._n);
}
For this example the result = a.Divide(b) transforms into result = Divide(a,b)
Notice that now you have a._n and a._d which is the first argument of function Divide
As a conclusion the expression a/b is just a very nice way of writing Divide(a,b) that c++ standard allows.

Complex class [PrintMax]

So I am working on "TEMPLATES" and I'm required to make a 3 attempt of a function called PrintMax -it's obvious what it does-, to print the maximum element in an array of 3 elements, each attempt is for a different data type in this array -double/int/complex-. So I'm required to first, create the class Complex, and its required operator overloads, after that I use the PrintMax function as template function to work on the 3 types of arrays.
The problem here lies within the 3rd array of course, I can't write the elements of Complex into the array in this for ( a + bi ), because this is my class Complex :
class Complex
{
private :
int imaginary;
int real;
public:
Complex (int = 0, int = 0);
~Complex ();
int getImaginary();
int getReal();
void setImagniary(int i);
void setReal (int r);
bool operator > (Complex&);
};
You can notice, I overloaded operator > to check, but I also have a little problem besides not being able to write the elements in that way, the second problem is I can't -or sleepy and my brain is dying- calculate which is maximum in this array of Complex numbers :
// Input: Complex Array
// 1+3i, 2+4i, 3+3i
// Expected Output: 2+4i
So I want to assign them in the array with this form : Arr[3] = {1+3i, 2+4i, 3+3i};
Why is that the expected output, why not 3+3i ?
Thanks for reading ~
It seems to me that you are looking for something like:
template <typename T> void PrintMax(T array[])
{
// It is assumed that array has 3 elements in it.
std::cout <<
array[0] > array[1] ?
(array[0] > array[2] ? array[0] : array[2]) :
(array[1] > array[2] ? array[1] : array[2])
std::endl;
}
You could use something like the following. Note that there are no range checks in the code, it is just to demonstrate a way how you could solve your problem.
Plus i would suggest you to use a container (eg. std::vector) instead of plain arrays.
#include <algorithm>
#include <cmath>
#include <iostream>
class Complex {
private:
int imaginary;
int real;
public:
Complex(int r, int i) :
imaginary(i), real(r) {
}
~Complex() {
}
int getImaginary() const {
return imaginary;
}
int getReal() const {
return real;
}
void setImaginary(int i) {
imaginary = i;
}
void setReal(int r) {
real = r;
}
double getAbsolut() const {
return std::abs(std::sqrt(std::pow(imaginary, 2) + std::pow(real, 2)));
}
friend bool operator<(const Complex& lhs, const Complex& rhs);
friend std::ostream& operator<<(std::ostream& stream,
const Complex& complex);
};
bool operator<(const Complex& lhs, const Complex& rhs) {
return lhs.getAbsolut() < rhs.getAbsolut();
}
std::ostream& operator<<(std::ostream& stream, const Complex& complex) {
stream << "Complex(" << complex.real << "+" << complex.imaginary
<< "i)";
return stream;
}
template<int size, class T>
void getMax(const T arr[]) {
T max_value = arr[0];
for (size_t i = 1; i < size; ++i) {
max_value = std::max(max_value, arr[i]);
}
std::cout << "max: " << max_value << std::endl;
}
int main(int argc, char **argv) {
Complex arr_complex[] = { Complex(3, 3), Complex(2, 4), Complex(1, 3) };
int arr_int[] = { 3, 5, 1 };
double arr_double[] = { 2.3, 5.6, 9.1 };
getMax<3>(arr_complex);
getMax<3>(arr_int);
getMax<3>(arr_double);
return 0;
}

Overloaded operator must take zero or one argument

Yes, this question has been asked before, but the problem was that the operator was a member function and that's not the case here. These are my files:
minmax.h
#ifndef MINMAX_H
#define MINMAX_H
class MinMax
{
private:
int m_nMin;
int m_nMax;
public:
MinMax(int nMin, int nMax);
int GetMin() { return m_nMin; }
int GetMax() { return m_nMax; }
friend MinMax operator+(const MinMax &cM1, const MinMax &cM2);
friend MinMax operator+(const MinMax &cM, int nValue);
friend MinMax operator+(int nValue, const MinMax &cM);
};
#endif // MINMAX_H
minmax.cpp
#include "minmax.h"
MinMax::MinMax(int nMin, int nMax)
{
m_nMin = nMin;
m_nMax = nMax;
}
MinMax MinMax::operator+(const MinMax &cM1, const MinMax &cM2)
{
//compare member variables to find minimum and maximum values between all 4
int nMin = cM1.m_nMin < cM2.m_nMin ? cM1.m_nMin : cM2.m_nMin;
int nMax = cM1.m_nMax > cM2.m_nMax ? cM1.m_nMax : cM2.m_nMax;
//return a new MinMax object with above values
return MinMax(nMin, nMax);
}
MinMax MinMax::operator+(const MinMax &cM, int nValue)
{
//compare member variables with integer value
//to see if integer value is less or greater than any of them
int nMin = cM.m_nMin < nValue ? cM.m_nMin : nValue;
int nMax = cM.m_nMax > nValue ? cM.m_nMax : nValue;
return MinMax(nMin, nMax);
}
MinMax MinMax::operator+(int nValue, const MinMax %cM)
{
//switch argument places and pass them to previous operator version
//this avoids duplicate code by reusing function
return (cM + nValue);
}
main.cpp
#include <iostream>
#include "minmax.h"
using namespace std;
int main()
{
MinMax cM1(10, 15);
MinMax cM2(8, 11);
MinMax cM3(3, 12);
//sum all MinMax objects to find min and max values between all of them
MinMax cMFinal = cM1 + 5 + 8 + cM2 + cM3 + 16;
cout << cMFinal.GetMin() << ", " << cMFinal.GetMax() << endl;
return 0;
}
The message reads error: 'MinMax MinMax::operator+(const MinMax&, const MinMax&)' must take either zero or one argument
To turn my comment into an answer:
You're defining your function as a member function by putting MinMax:: in front of it, so they are member functions.
MinMax MinMax::operator+(const MinMax &cM, int nValue)
{ // should be operator+ without the MinMax:: at the front.
//compare member variables with integer value
//to see if integer value is less or greater than any of them
int nMin = cM.m_nMin < nValue ? cM.m_nMin : nValue;
int nMax = cM.m_nMax > nValue ? cM.m_nMax : nValue;
return MinMax(nMin, nMax);
}
you can see it working here
As you've said, they are not member functions.
Therefore, in their definitions, the MinMax:: prefix is incorrect and should not be there.