Why does the below C++ program output "ACCA"? Why is operator int() called twice?
#include "stdafx.h"
#include <iostream>
using namespace std;
class Base {
public:
Base(int m_var=1):i(m_var){
cout<<"A";
}
Base(Base& Base){
cout<<"B";
i=Base.i;
}
operator int() {
cout<<"C";
return i;
}
private:
int i;
};
int main()
{
Base obj;
obj = obj+obj;
return 0;
}
First, this line:
Base obj;
Default-constructs object obj by picking the constructor that accepts an integer, with default value 1. This is responsible for the first A being printed to the standard output.
Then, this expression:
obj + obj
Requires picking a viable overload of operator +. In this case, since obj has a user-defined conversion to int, the built-in operator + is picked, and both arguments are converted to int. This is responsible for the two Cs being printed to the standard output.
Then, the assignment to obj in:
obj = obj + obj
Needs to invoke the implicitly generated operator = for Base. The implicitly generated operator = has signature:
Base& operator = (Base const&);
This means that the expression on the right side of the equal sign, which is of type int, must be converted into a temporary Base object from which obj is assigned (the reference parameter of the implicitly-generated operator = is bound to this temporary).
But the creation of this temporary from an int in turn requires invoking the converting construction of Base that accepts an int again, which is responsible for the second A being printed to the standard output.
operator int() is called twice because you haven't overloaded operator+. The compiler doesn't know how to add a Base to a Base, so they are converted to int (since you taught it how to do that), which it does know how to do. The following code prints ADA:
#include <iostream>
using namespace std;
class Base {
public:
Base(int m_var=1):i(m_var){
cout<<"A";
}
Base(Base& Base){
cout<<"B";
i=Base.i;
}
operator int() {
cout<<"C";
return i;
}
int operator+(Base& Base)
{
cout<<"D";
return i+Base.i;
}
private:
int i;
};
int main()
{
Base obj;
obj = obj+obj;
return 0;
}
When you construct the object, you get the first "A":
Base obj;
When you specify to add obj+obj, the compiler needs to figure out a way to use + on obj. Since you didn't override an operator+ for Base, the conversion to int() gets called for each side of the equation:
obj+obj
This prints "CC".
Then, you assign to obj, which is of type Base, so the constructor which can accept an int (i + i from the int() operator) is run, which prints "A":
obj = obj+obj; // Assignment prints "A"
obj = obj+obj;
^^^--------obj converted to int here
^^^----obj converted to int here
^^^^^------------Base(int) ctor and default operator= called here
Overloading cast operators is not generally a good idea unless you understand the costs and know for a fact that the benefits in your specific case outweigh them.
how does below C++ program computes to "ACCA" ?
The first letter shown is 'A'. This output is related to this line:
Base obj;
... in which you are creating a new instance of Base.
The next line is a bit complicated:
obj = obj+obj;
Normally, this is translated to obj.operator+( obj ), but you don't have operator + overloaded in class Base, so this translation is not valid. The remaining possibility is that operator + is actually the numeric add operator.
And yes, this is possible, since you have provided a cast to int. So it is possible to convert each term of the equation in an int... and therefore operator int is called twice. The actual number of times operator int is called depends on the optimizations activated. For example, the compiler could realise that both terms are the same, and then create a new temporary once the operator int has been called the first time. In that case, you would see CA instead of CC.
Finally, the assignment expression obj.operator=( temp ) is executed. And here the keyword is temp. In order for the default operator= to work, since it is not overloaded, you have to have a Base object at the right. It is actually possible to have it, since Base uses an int to build new instances. Okay, so the result of obj + obj was an int (say it is called 'x') number, and the compiler creates a temporary object of class Base which is constructed with number x, as the following line was executed:
Base temp( x );
That's the way the final letter seen is an 'A'. Again, many compilers can avoid the building of temporaries on some cases, so it is possible not to see an 'A' at the end.
Note that this line:
obj = obj + obj
Was thus decomposed in:
int x = ( (int) obj ) + ( (int) obj );
Base temp( x );
obj = temp;
The final instruction has the result of as if the memory in which obj sits will be occupied with the contents of temp (that's the role of the default copy constructor, which executes operator= for each member of the class, see again the 'rule of three').
Operator overloading involves a lot of issues that maybe are not foreseen if you don't have a more or less deep knowledge of the language, as you can see. Take also into account that languages like Java totally prevent its use, while C# permits it from a controlled perspective.
You refer to obj twice in the expression obj+obj and each such reference has to be converted to an integer.
It's not impossible (although it is a horrible idea) that such a conversion could be "stateful" - that is, it could by design return a different value each time it is called. After all, the value represented by obj may change (it could be a counter or something like that). So the compiler has to evaluate it afresh for each reference.
It's call once per operand, it doesn't matter if it is the same instance.
obj = obj+obj;
It "casts" the first operand to an int, and then the second one.
You need to overload the operator + if you want to avoid this implicit cast.
It calls operator int() twice because it needs to convert both obj to int before it can add them.
The first A comes from
Base obj;
The two Cs come from converting obj in obj+obj to int as you didn't overload the operator +.
The last A comes from obj = conversion of the resulting int to obj.
Related
This is a rather simple concept. I have an arithmetic operator and I wish for the operation to update not create an object. Essentially,
MyType A;
MyType B;
MyType C;
A = B - C;
A = C - B;
The statement A = B - C should not call the constructor for MyType again since A is already created, i.e. the constructor should only be called 3 times in this program. Is there some way to achieve this while maintaining a nice syntax? I suspect that I could let the operator function know not to create an object but rather to use some reference. Is there a more streamlined way to do this using some c++ syntax unknown to me?
class MyType
{
MyType* OperatorReturnObj;
MyType operator-(const MyType& Left, const MyType& Right)
{
// This removed and replaced with SetOperatorReturnObj function
// MyType OperatorReturnObj();
OperatorReturnObj= Left - Right;
return OperatorReturnObj;
}
void MyType SetOperatorReturnObj(MyType* Ref)
{
OperatorReturnObj = Ref;
}
};
Without ugly tricks like creating pool of objects and using them internally (where complications would be more expensive than any benefits for this case), there is no way to achieve this. Problem is that statement:
A = B - C;
is equal to:
A.operator=( operator-( B, C ) );
as you can see operator-( B, C ) has to be executed first and provide result somewhere. So you either have to change syntax like:
A += B; A -= C; // or even
(A += B) -= C; // or maybe
A += B -= C;
or use regular syntax and if you need efficiency implement move semantics.
After some thought you can create object of type MyTypeExression which does not do actual calculations but remember arguments and operations and only do them later when MyType::operator=(MyTypeExression) is executed. Though for that to work you probably need a wrapper with smart pointer for MyType so MyTypeExression does not have to copy it's arguments. So this solution can be considered as complicated trick I mentioned before.
I wish for the operation to update not create an object
For A = B - C;, A will be updated, by operator=.
More particular, operator- 's return value is passed by value, a temporary variable has to be created inside operator- and then copied/moved to A.
BTW1: OperatorReturnObj= Left - Right; will cause an infinite recursion.
BTW2: MyType A(); is a function declaration indeed. Most vexing parse
You cannot.
In A = B - C, first the B - C expression is evaluated. Then the result is copied to A.
The B - C expression knows nothing about A, so it is not possible to update A directly.
You can overload the assignment operator but this will not prevent the creation of a new object.
Some tips:
First of all, you didn't specified how to initialize the internal pointer attribute, so at this moment it points to an unspecified value in the memory stack.
Second, the operator- method(!) isn't defined like you did. look at "binary arithmetic operators"
binary operators have to return a reference to the object they are called from.
Third, the object itself is passed "automagically" to its methods, and its available as the this pointer.
So you don't have to pass it as the first parameter.
Finally, to return a reference you have to return the value, and not the pointer : --> *this.
So an expression like A=B+C is evaluated to:
A.operator=(B.operator+(C))
So B+C is different than C+B. (I don't enter in the details of inheritance here..)
Inspired from the same previous link above:
class X {
int internalprivatevalue;
//....
public:
X& operator+(const X& second) {
// actual addition of second to *this takes place here
// e.g. internalprivatevalue+=second. internalprivatevalue;
return *this; // return the result by reference!!
}
}
Hope to have clarified a little more your doubts.
I realize that there are examples after examples of overloading the assignment operator on the web, but I have spent the last few hours trying to implement them in my program and figure out how they work and I just can't seem to do it and any help would be greatly appreciated.
I am trying to implement an overloaded assignment operator function.
I have 3 files working, the Complex.h header file, a Complex.cpp definition file, and a .cpp file I'm using as a driver to test my Complex class.
In the Complex.h header file my prototype for the assignment operator:
Complex &operator= (Complex&);
And so far what I have for the definition of the overloaded operator in my .cpp file is:
Complex &Complex::operator=(Complex& first)
{
if (real == first.real && imaginary == first.imaginary)
return Complex(real, imaginary);
return first;
};
And the way I'm calling my assignment operator in my functions is:
x = y - z;
So specifically, my problem is that when I call the overloaded assignment operator with x = y -z, it doesn't assign the passed in value to x when I return the passed in value and I'm unable to figure out why from numerous examples and explanations on the web, any help would be greatly appreciated and I thank you for any help ahead of time.
I think you need the following operator definition
Complex & Complex::operator =( const Complex &first )
{
real = first.real;
imaginary = first.imaginary;
return *this;
};
You have to return reference to the object that is assigned to. Also the parameter should be a constant reference. In this case you may bind the reference to a temporary object or you have to write also a move assignment operator.
In your implementation of the copy assignment operator you do not change the assigned object.:) You simply create a temporary and return reference to this temporary or return reference to first.
Assignment takes in two objects, the object to be assigned to, and the object with the desired value.
Assignment should:
modify an existing object, the object being assigned to
Assignment should not:
create a new object
modify the object that has the desired value.
So let's say the object type we're dealing with is:
struct S {
int i;
float f;
};
A function that performs assignment might have the signature:
void assignment(S &left_hand_side, S const &right_hand_side);
And it would be used:
S a = {10, 32.0f};
S b;
assignment(b, a);
Notice:
the left hand side object is modifiable, and assignment will modify it, rather than create a new object.
the right hand side object, the object with the desired value, is not modifiable.
Additionally, in C++ the built-in assignment operation is an expression rather than a statement; it has a value and can be used as a subexpression:
int j, k = 10;
printf("%d", (j = k));
This sets j equal to k, and then takes the result of that assignment and prints it out. The important thing to note is that the result of the assignment expression is the object that was assigned to. No new object is created. In the above code, the value of j is printed (which is 10, because j was just assigned the value 10 from k).
Updating our earlier assignment function to follow this convention results in a signature like:
S &assignment(S &left_hand_side, S const &right_hand_side);
An implementation looks like:
S &assignment(S &left_hand_side, S const &right_hand_side) {
// for each member of S, assign the value of that member in
// right_hand_side to that member in left_hand_side.
left_hand_side.i = right_hand_side.i;
left_hand_side.f = right_hand_side.f;
// assignment returns the object that has been modified
return left_hand_side;
}
Note that this assignment function is not recursive; it does not use itself in the assignment, but it does use assignment of the member types.
The final piece of the puzzle is getting the syntax a = b to work, instead of assignment(a, b). In order to do this, all you have to do is make assignment () a member function:
struct S {
int i;
float f;
S &assignment(S &left_hand_side, S const &right_hand_side) {
left_hand_side.i = right_hand_side.i;
left_hand_side.f = right_hand_side.f;
return left_hand_side
}
};
Replace the left_hand_side argument with *this:
struct S {
int i;
float f;
S &assignment(S const &right_hand_side) {
this->i = right_hand_side.i;
this->f = right_hand_side.f;
return *this;
}
};
And rename the function to operator=:
struct S {
int i;
float f;
S &operator=(S const &right_hand_side) {
this->i = right_hand_side.i;
this->f = right_hand_side.f;
return *this;
}
};
int main() {
S a, b = {10, 32.f};
S &tmp = (a = b);
assert(a.i == 10);
assert(a.f == 32.f);
assert(&tmp == &a);
}
Another important thing to know is that the = sign is used in one place that is not assignment:
S a;
S b = a; // this is not assignment.
This is 'copy initialization'. It does not use operator=. It is not assignment. Try not to confuse the two.
Points to remember:
assignment modifies the object being assigned to
assignment does not modify the object being assigned from.
assignment does not create a new object.
assignment is not recursive, except insofar as assignment of a compound object makes use of assignment on all the little member objects it contains.
assignment returns the object after modifying its value
copy initialization looks sort of like assignment, but has little to do with assignment.
An overloaded assignment operator should look like this:
Complex &Complex::operator=(const Complex& rhs)
{
real = rhs.real;
imaginary = rhs.imaginary;
return *this;
};
You should also note, that if you overload the assignment operator you should overload the copy constructor for Complex in the same manner:
Complex::Complex(const Complex& rhs)
{
real = rhs.real;
imaginary = rhs.imaginary;
};
this might be a noobie question but this confuses me, especially when it comes to this pointer.
How do I know which object "this" pointer is pointing to? I can provide an example where that confuses me... Say you had this code
#include<iostream>
using namespace std;
class someClass{
int var;
//2 constructors here, one with no arguments, one with giving a value to var(not important)
someClass operator+(someClass object){
someClass rObject;
rObject.var = this->var + object.var //and here is my problem
}
};
int main() {
someClass a(20);
someClass b(30);
someClass c;
c=a+b; //????????
//rest of the code not important
}
In this case the "current object" would be the object a, but how does that make sense if we just switch sides so it's c=b+a the current object would become b... I am confused... What determines the current object?
You have chosen the more involved example: operators. In general it is easier to reason about other member functions. Consider:
struct T {
int value;
void foo() { std::cout << this->value << '\n'; }
};
int main() {
T t;
t.foo();
}
How do you know which is the current object inside foo()? It is the object on the left of the dot operator in the expression, in this case t. (Well, in this case there is no other object at all in the program!)
Now going back to operators, for binary operators in particular, many of them can be implemented in two forms, as a free function taking two arguments or as a member function taking a single argument. There is a direct transformation that the compiler will do for you in both cases:
struct T {
int value;
T operator+(T const & rhs) { T tmp; tmp.value = this->value + rhs.value; return tmp; }
};
T operator-(T const & lhs, T const & rhs) {
T tmp; tmp.value = lhs.value - rhs.value; return tmp;
}
int main() {
T a, b; a.value = 1; b.value = 2;
a - b;
a + b;
}
Then the compiler encounters the expression a - b it searches for the two possible forms of the operator, it finds that it is a free function and it binds lhs to a and rhs to b, transforming the expression into operator-(a, b). In the case of a + b, the compiler again searches for the operator and finds it as a member function, at this point the transformation becomes a.operator+(b) and the this pointer inside the member function refers once again to the object to the left of the dot operator.
Non-static class methods have an implicit first argument this of the class type. So when you write:
operator+(someClass object)
You are actually getting this:
operator+(someClass* this, someClass object)
And now you can see: the left-hand side of a binary operator is the first argument, and the right-hand side is the second argument (by convention, and because it makes more sense than the other way around).
When you execute a+b, that invokes operator +(someClass) on object a. Therefore, this is a.
It helps to first consider an easier operator, namely operator +=. It may appear to be a more advanced operator, but that's because we learned arithmetic using +. If you look at your code, you see that you typically need three objects for + c=a+b whereas += just needs two: b += a.
Now in b += a the this pointer should point to the object you're changing, i.e. b. That's the first object. To keep things simple, for all binary operators this points to the first object.
Can some one explain how below program becomes infinte loop of "AabAabAab.."
#include "stdafx.h"
#include <iostream>
using namespace std;
class Base {
public:
Base(int j=1):i(j)
{cout<<"B";}
private:
int i;
};
class Case{
public:
Case(int j=1):i(j) {cout<<"A";}
operator Base() { cout<<"ab"; return *(new Case); }
private:
int i;
};
int main()
{
Base obj = Case();
return 0;
}
Base obj = Case();
This calls the Case default constructor, printing A. Then, there is a conversion to Base via this operator, which has an infinite recursion:
operator Base() { cout<<"ab"; return *(new Case); }
Because it attempts to return a Case instance (prints abA), which must be converted to Base, which invokes the conversion operator, which creates a Case instance (prints abA), which must be converter to Base, which...
Can some one explain how below program becomes infinte loop of "AabAabAab.."
Not really infinite. This will eventually crash your program because of stack overflow. This is what's going on. Here:
Base obj = Case();
You are creating a temporary object of type Case and using it to initialize an object of type Base.
The only way this can be done is by picking the user-defined conversion operator of Case, which can return a Base.
Now this conversion operator in turn happens to create a temporary object of type Case, from which the return value of the operator should be initialized.:
return *(new Case);
Since the return value is itself of type Base, the temporary now has to be converted to an object of type Base - and since the temporary has type Case, the same user-defined conversion operator is invoked again.
This is what attempts to generate an infinite recursion. Since each function call requires creating a stack frame, however, your neverending recursion will eventually cause a stack overflow, and your process will be terminated.
I have doubt whether we can do the following or not.
Suppose I have created two instance of class A i.e. obj1 and obj2 and class A has member function show().
Can I use the following?
(obj1+obj2).show()
If yes, how? If no, why it is not possible?
Yes it is possible, just implement operator+ for A and have it return a class of type A:
#include <iostream>
class A
{
public:
explicit A(int v) : value(v) {}
void show() const { std::cout << value << '\n'; }
int value;
};
A operator+(const A& lhs, const A& rhs)
{
A result( lhs.value + rhs.value );
return result;
}
int main()
{
A a(1);
A b(1);
(a+b).show(); // prints 2!
return 0;
}
You can do it if you overload the + operator in such a way that it takes two arguments of type A and yields an object that has a method named show.
Yes you can use it if you have overloaded the + operator of class A to return an obect of class A.
If obj1+obj2 does return an object that have a show() function member, then yes it's possible.
If not, it is not.
So, it depends on the operator+ function that is used here, that depends on both types of obj1 and obj2.
obj1+obj2 is an expression that have a type, the type of the object returned by the operation, like any expression. Now, once the expression is executed, you have this object. But as here you don't associate it to a name (using assignation for example), it is a "temporary", meaning it will be destroyed at the end of the full expression.
So, if the resulting temporary object's type does provide a show() function then you can call it like you did.
If it don't provide a show() function, then you're trying to call a function that don't exists.
So in any case, the compiler will stop you, it will not be a runtime error.
I would be you, I would setup a minimal test project just to play with those principles.
Write an operator overload for + operator and define the operation you want on that.
In the operator overload for + operator just update the logic you want like adding the individual member variables or concatenating the names etc meaningfully based on your use case
Then you can call That new object.Show() function just like an object calling member function.
Depends on what the result type of obj1+obj2 is and whether .show() is a constant method.
No! The result of (obj1+obj2) isn't object. You may overload "="
and use:
obj3 = obj1 + obj2;
obj3.show();