I am following this tutorial on operator overloading: https://www.geeksforgeeks.org/operator-overloading-c/
Code snippet:
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) { real = r; imag = i; }
// This is automatically called when '+' is used with
// between two Complex objects
Complex operator + (Complex const& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << endl; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
}
My question is, how does c++ know what to pass in to &obj and how does it know what to give to real and imag within the operator function? Like how does it know 10 for c1 goes to real and 2 for c2 goes to obj.real? It was never specified which object gets assigned to obj. Hell how does it even know to parse c1's values to real and imag within the operator function?
c1 is the object you're working with. That probably sounds confusing, so let me explain.
When you do this:
c1 + c2;
ignoring the return value for a second, that code is the same as doing this:
c1.operator+(c2);
So, c1 is the base object on which the operator is called. In the same way that c1.print() uses c1's values, calling the operator uses c1's values by default, so to speak.
Why is c1 called here and not c2? Like why isn't it the same as:
c2.operator+(c1);
This is because c1 is on the left hand side. If c2 were on the left hand side, like in the example c2+c1, then operator+() would get called on c2 instead.
So, in short (and other words), C++ uses operator+()(and similar operators) by calling operator+() in the following format:
left.operator+(right);
This allows you to use real and imag like you would in print() for the left side's member variables, and other.real and other.imag for the right side's variables.
So, in the comments you asked a couple more questions that I figure might take more than a comment or two to answer, but are worth answering. So, here goes.
So if you call that + function, it ignores the c3 which I actually assumed was what we were working with, and looks at the left and right hand side of the operation to know what to assign to each side?
Correct. As far as inside the function, operator+() only looks at the objects immediately beside it (in this case, c1 and c2) to perform the calculation.
I am surprised because c3 technically is what I am working with,
Ah, okay. Not for the calculation itself. Let's look at your operator+() closely again:
Complex operator + (Complex const& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
Here, you have a current object (which is where real and imag come from) and another object (which is where obj.real and obj.imag come from). It's these that make up c1 and c2. These are the numbers you are actually adding.
c3, on the other hand, is the result of this addition. If I have something like this:
4 + 3 = 7
The operation 4+3 will have a result: 7. That's what c3 is here. Well, technically, that's what res is here. By returning res, you're returning the result. And in the case of c3, it's setting it's value to the returned result of operator+() via the assignment (=) operator.
Secondly, why do I need to return res?
Already sort of covered that, but to be clear: res is the result of the operation. C++ wouldn't know how to get the result otherwise.
res is only a local variable, wouldn't it's data get destroyed once + is done, instead of it passing the summation data to real and imag?
You seem to be confusing returning by reference and returning by value. If you return a local variable by reference, absolutely. This will get destroyed. However, if you return by value, the result gets copied out almost by definition, so you're totally fine here in this example.
Related
I am performing complex addition & multiplication, the following code produces worng results despite correct formulation.
#include<iostream>
using namespace std;
class Complex{
int real,img;
public:
Complex(int r=0,int i=0){
real=r;
img=i;
}
Complex operator + (Complex &);
Complex operator * (Complex &);
void print(){
cout<<real<<" + "<<img<<"i"<<endl;
}
};
Complex Complex::operator + (Complex &c2){
//checkig the variables true value
cout<<real<<endl;
cout<<c2.real<<endl;
return(real+c2.real,img+c2.img);
}
Complex Complex::operator * (Complex &c2){
return(real*c2.real-img*c2.img,real*c2.img+img*c2.real);
}
int main(){
Complex c1(10,5), c2(2,4);
Complex c3 = c1 + c2;
c3.print();
Complex c4 = c1 * c2;
c4.print();
return 0;
}
Actual results
9 + 0i
50 + 0i
Expected results
12 + 9i
0 + 50i
You are getting wrong output because you are not returning any Complex datatype.
You need to change return(real+c2.real,img+c2.img); into return Complex(real+c2.real,img+c2.img);
Same case for multiplication.
This code:
return(real+c2.real,img+c2.img);
doesn't do what you think it does.
It's evaluating real + c2.real, img + c2.img using the comma operator and then passing the result of that expression to the constructor for Complex. That generates the results you're seeing where the imaginary value is 0 and the real value is the expected imaginary value - the calculated real value is being discarded and the calculated imaginary value is being passed to the Complex constructor.
You can fix this by writing
return {real+c2.real, img+c2.img};
which will do what you actually want
The line
return(real+c2.real,img+c2.img);
is not interpreted as
return Complex(real+c2.real,img+c2.img);
Due to the comma operator, it is effectively interpreted as:
int tmp = (real+c2.real, img+c2.img);
return Complex(tmp);
The comma operator makes the value of tmp to be equal to img+c2.img.
Effectively, that line translates to
return Complex(img+c2.img);
Hence, you get the wrong result.
You can change that line to
return {real+c2.real,img+c2.img};
Better yet, make it more readable and use
return Complex(real+c2.real,img+c2.img);
Update the second function appropriately.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 5 years ago.
This is my main function:
int main(){
Complex c1(1.0, 5.0);
Complex c2(3.0,-2.0);
Complex c3(1.0, 2.0);
cout << "c1 + c2 + c3 = "
<< c1 + c2 + c3 << endl;
return 0;
}
This is the function I use to add up the required numbers
Complex& operator+(const Complex & x, const Complex & y){
Complex c;
c.a = x.a + y.a;
c.b = x.b + y.b;
return c;
}
a and b are private double variables in my class.
On running my program, I seem to get the output as 1+2i ie(c3) and it only seems to work properly when I add only 2 objects. Is there any way I can tweak my existing code to allow it to work for up-to n terms?
Your operator + returns a reference to the local variable c, which gets destroyed after it is done. Any further use of the result leads to undefined behavior.
You need to return a value, so it gets copied (or a rvalue), but not a reference:
Complex operator+(const Complex & x, const Complex & y)
{...}
I'm going over the basics of overloaded operators, specifically the assignment operator. I'm trying to understand the use of overloading in dictating copy and move behavior by following this:
operator overloading
I find the example they give to be quite unclear.
This is the basic code I've written so far to illustrate overloading. How can this code be edited to illustrated the use of overloading in customizing copy and move behavior?
class Distance
{
public:
int feet, inches;
Distance()
{
feet = 0;
inches = 0;
}
Distance(int f, int i)
{
feet = f;
inches = i;
}
auto operator=(Distance &D)->void //Use operator to perform additional operation (adding 100)
{
feet = D.feet + 100;
inches = D.inches + 100;
}
};
int main()
{
Distance D1;
D1.feet = 10;
D1.inches = 12;
Distance D2;
D2 = D1;
std::cout << D2.feet << std::endl;
}
You shouldn't use assignment operator like that (even if you can). Assignment operator with additional operation could be used for example for counting how many assignments was made. Altering data this way leads to confusion and human error during use of the interface. You expect the code to work in some way, in case of assignment operator, it is copying values. Just follow how built-in types work and implement your overloaded operators that way. You wouldn't multiply volumes for operator+(), right? That wouldn't make any sense.
Additional operation in this case could be e.g.:
static int assignmentCount = 0;
auto operator=(Distance &D)->void
{
feet=D.feet;
inches=D.inches;
std::cout << "Made assignment"; //Just some debug stuff
assignmentCount++; //Count assignments made
}
Don't forget, that you have put there void as return type, which disables you to do following D1=D2=D3, which could be useful in some cases. Returning reference to receiving value is common practice.
I recommend reading Professional C++ by Marc Gregoire, or one of Stroupstrup's books. My recent experience is, that online sources can lead to some sort of confusion and books are generally better for learning basics.
I am a beginner at c++ can anyone explain me this code:
#include <iostream>
void display(int b)
{
std::cout << b << std::endl;
}
int main()
{
int a;
display(a=10);//display 10
std::cout << a << std::endl;//also display 10
return 0;
}
I know we can use = operator to set default values for a function parameters, but here it's in the function call, apparently "disply(a=10)" pass the value 10 to the function and store it in the variable "a" at the sametime.
is this correct coding in c++ and can anyone explain the assignment part?
The line
display(a=10);//display 10
equals to:
a = 10;
display(a);
This is because the value of the clause a = 10; is a.
I think this answers your question.
You need to know about = operator more. Not only is it assign rhs (right hand side) value to lhs (left hand side), but also it refers to the lhs.
Suppose this code:
a = b = c;
is exactly equal to
a = (b = c);
because = is right-associative.
If c is 10, the code assign 10 into b, and assign the value of b into a. So now a == b == c == 10.
The built-in assignment operator =
is right-associative
which means it groups to right, e.g. a = b = c means a = (b = c),
is an lvalue expression that refers to the left hand side.
Note that in C an assignment produces a pure value, while in C++ it produces a reference (in the common language meaning of referring).
This means that you can assign a value to multiple variables:
a = b = c = 12345;
which is parsed as
a = (b = (c = 12345));
which first copies 12345 to c, then copies c to b, then copies b to a.
And it means that you can assign to the result of an assignment:
((a = b) = c) = 12345;
which first copies the b value to a, then copies the c value to a, then copies 12345 to a, leaving b and c unchanged…
In your case, the code
display(a=10);
is equivalent to
a = 10; display( a );
Since the display function takes an int by value, this is equivalent to
display( 10 )
but if display had a reference argument then it could not be rewritten this way.
A common pitfall is to write
if( x = 12345 )
when one means to do a comparison,
if( x == 12345 )
Many compilers will warn about the first if the warning level is upped, as it should be.
More guaranteed ways to detect it include
Using const everywhere it can be used.
x can’t be assigned to when it’s const. This is my preferred solution.
Writing if( 12345 == x ).
Some people prefer this, but I find it hard to read, and as opposed to const it only helps to avoid the mis-typing when the writer is already, at that very point, very aware of the problem.
Defining a custom if construct via a macro.
Technically this works, also for other constructs that use boolean conditions, but in order to be useful such a macro should be short, and this runs the risk of name collision. It's also hard on maintainers who are unfamiliar with the (effectively) custom language.
In C++03 the standard library required that any container element type should be assignable, and the assignable criterion required that a custom assignment operator T::operator= should return T& (C++03 §23.1/4) – which is also a requirement on the built-in assignment operator.
Until I learned that I used to define assignment operators with result type void, since I saw no point in supporting coding of expressions with side-effects (which is generally a bad practice) at the cost of both efficiency and verbosity.
Unfortunately this is a case where in C++ you pay for what you don’t use and generally should not use.
The assignment <variable> = <value> in C, C++ is and expression which means it have a value and this value is, of course, the <value> you've just assigned.
That's the reason why you can assign a value to multiple variables like this:
a = b = c = 1;
because internally it works something like this
a = value of (b = value of (c = 1));
and since the assignment does indeed have a value, the value of (c = 1) is
1, value of (b = (c = 1)) is 1 and therefore we get a = 1. And as a
If the assignment wouldn't be an expression and didn't have a value, we would
get an error, because value of (c = 1) would not exist and we would get a
syntax error.
So in your code, display(a=10); means: *set value a to 10 and pass the
resulting value (which would be 10) as an argument to the function display.
It is correct.
display(a=10); //It assigns 10 to a and 10 is passed as the parameter to function.
I am fairly new to C++ and I have been reading and writing some of my own code. I see these operators from time to time, if that is even the right word to use?
+= // Not sure what it means
So my question is: what do they mean/do, and what are they called?
For further reference, I'd like to know what they are called so I can easily look it up (searching simply for "+=" for instance yielded nothing).
Edit: For anyone else who does not know the meaning (or in my case knew the name of these) I found this Wikipedia link which might come of handy to other people: http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
Yes, these are operators. More specifically, they are known as compound assignment operators. Here's the full list of them:
*= /= %= += -= >>= <<= &= ^= |=
They are defined like so:
The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once.
So x += 5; is almost the same as x = x + 5;.
You can think of it as a modifying addition. If you just do x + 5, the result of the expression is what you get if you add x and 5 together, but x hasn't changed. If you do x += 5;, x actually has 5 added to its value.
its just an abbreviation:
a+=2; means a=a+2;
of course as many operators: you can overload it to give it alternative meaning, ans actually we do it often to provide meaning for example in the case what it means to add int to our class SomeClass:
SomeClass s;
s+=1; //operator+=(SomeClass& s, int i){} is used here
class A{
public:
A():i_(123){}
~A(){}
int i(){return i_;}
A const& operator+=(int i){
std::cout<<"operator+=";
this->i_=i_+i;
}
private:
int i_;
};
int main(int argc, char** argv) {
A a1;
a1+=3;
std::cout<<a1.i();
return OK;
}
output: operator+=126