Class constructor has more priority over the "=" operator? - c++

I overloaded the operator "=" to do something, but instead it goes and uses the constructor
class Date
{public:
int x;
public:
Date(int v1)
{
x = v1+1;
}
Date& operator=(Date& d)
{
x = x - 1;
}
public:
~Date() {};
};
int main()
{
Date d = 1;
cout << d.x;
//delete d;
return 0;
}
I was expecting to print 0 but instead it prints 2(uses the constructor). Why is that? Also why won't it let me delete d? it says it must be a pointer to a complete object type.

It should get priority, because this
Date d = 1;
Is not assignment, it's an object declaration with initialization. Initialization of class objects in C++ is the domain of constructors. Don't let the syntax (using = 1 as an initializer) confuse you.
To get the assignment operator called, the left hand side must be an existing object whose initialization already happened. Assignment only applies to preexisting objects. So if you add a statement like this:
d = 1;
It could call the assignment operator as you expect (after some other errors are fixed).
Also why won't it let me delete d? it says it must be a pointer to a complete object type.
The error seems pretty self explanatory to me. You can only call delete on a pointer operand. And the pointer must be pointing at an object previously create with new.

Related

How is this struct initialisation working?

I came across a piece of code that had structs and I am now thoroughly confused about how automatically the constructor of the struct is being called. I made a dummy code just to understand the concept. For example,
struct obj {
int a = 0, b = 2;
obj (int aa) {
a = aa;
}
obj (int aa, int bb) {
a = aa;
b = bb;
}
int getSum () {
return a+b;
}
};
void calcSum (obj o) {
cout << o.getSum() << endl;
}
int main()
{
calcSum(5);
return 0;
}
This does print 7. I believe that the single argument constructor of struct obj is automatically being called. If so, how can I make it automatically call the double argument constructor? I am unable to do so.
What is the name of this functionality?
Also please guide me to some good articles as I was unable to find any.
You can use a braced initialization list to invoke the constructor:
calcSum({5, 3});
A somewhat broad term for this feature of C++ is called "implicit conversion". If the type of the object being "assigned to" (or constructed, which in this case is a function parameter) does not match the type of the object being "assigned from", C++ has a long, long list of rules of implicit conversions that can be used to convert one type to another.
One of these rules involves a comma-separated list of values in braces. If it is specified for an object with an explicit constructor, the constructor get used to construct the object.
Note that this also invokes the same constructor as in the original code:
calcSum({5});
A constructor with one parameter does not need braces to be implicitly invoked.

Assignment Operator Overload in c++

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;
};

How do you know what is the current object?

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.

C++ operator overloading

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.

What is the default operation of the '=' operator?

I have a class, Number, which represents a double with two digits after the dot. Before I overloaded the = operator I ran some tests and got a little confused:
int main(int argc, char **argv) {
Number *w = new Number(1.111);
Number *q = new Number(3.444);
*w = *q;
std::cout << w->GetNumber() <<std::endl;
delete q;
std::cout << w->GetNumber() <<std::endl;
Number e(5.555);
Number t = e;
std::cout <<t.GetNumber() <<std::endl;
}
The output was
3.44
3.44
5.55
What is the default action of '=' on user defined objects when '=' is not overloaded?
I was under the impression that when writing:
*w = *q;
w points to q (like in Java). However, in my example I deleted q and w still had the correct values.
Anyway, I got same results when I made assignments without overloading = and with overloading =.
The default operation of the assignment operator is memberwise assignment:
class Foo
{
int i;
std::string s;
Bar b;
public:
Foo& operator=(const Foo& that)
{
i = that.i;
s = that.s;
b = that.b;
return *this;
}
};
If that's exactly what you need, you don't have to overload operator= manually.
If you have pointer members, only the pointers are copied, not the pointees, which can wreak havoc. Either use RAII types like std::vector in that case or disable copying by declaring the copy constructor and the assignment operator private or by inheriting from boost::noncopyable.
Note that Number t = e; does not call the assignment operator, because there isn't yet any object to assign to. Instead, the copy constructor is called, which does memberwise copy construction by default:
Foo(const Foo& that) : i(that.i), s(that.s), b(that.b)
{
}
Since you will probably ask: the thing after the colon is called an initializer list. It cannot be overstated that initialization and assignment are two very different concepts in C++.
It makes a copy of the object (deep copy) i.e. the q object's contents are copied into w. If you have not provided your own copy constructor - assignment operator pair then compiler will automatically generate one for you which copies each element of the source object to the elements of the destination object. Once this copy is created, it doesn't matter what you do with the original object.
*p = *q is equivalent to
(*p).operator=(*q);
The default assignment operator does the following: (I tried putting it in short but I can't beat the standard in terms of accuracy and conciseness, hence quoting it)
The implicitly-defined copy assignment operator for class X performs memberwise assignment of its subobjects. The direct base classes of X are assigned first, in the order of their declaration in the base-specifierlist, and then the immediate nonstatic data members of X are assigned, in the order in which they were declared in the class definition. Each subobject is assigned in the manner appropriate to its type:
— if the subobject is of class type, the copy assignment operator for the class is used (as if by explicit qualification; that is, ignoring any possible virtual overriding functions in more derived classes);
— if the subobject is an array, each element is assigned, in the manner appropriate to the element type;
— if the subobject is of scalar type, the built-in assignment operator is used.
As you can see, the left hand side object does not start referring to the right hand side object.
Default operator = perform memberwise copy of the object to the destination.
*w = *q assign the value of *q to *w;
w = q makes w point to the same object as q, but it leaks w.