I wanted to ask a question about operator overloading in C++.
I am a beginner in C++ and have been learning OOP.
Consider the following overloaded copy assignment operator:
class Base {
private:
int value;
public:
Base () : value {0}
{
cout << "Base No-args constructor" << endl;
}
Base (int x) : value {x} {
cout << "Base (int) overloaded constructor" << endl;
}
Base (const Base &other) : value {other.value} {
cout << "Base copy constructor" << endl;
}
Base & operator = (const Base &rhs) {
cout << "Base operator=" << endl;
if (this == &rhs)
return *this;
value = rhs.value;
return *this;
}
~ Base () {cout << "Base Destructor" << endl;}
};
I wanted to clarify two points.
I wanted to give my interpretation on (1).
If I have the following code in my main()
:
Base b {100}; // overloaded constructor
Base b1 {b}; // copy constructor
b = b1; // copy assignment
What I think happens is that the no args constructor is called for a1
, evidently because no arguments are passed into the construction of the object. When a2
is initialised, a temporary copy of a1
is made and then the operator is evaluated with respect to the Base
class, hence the Base
overloaded copy assignment block is run, and the a1
object is returned via return *this
to the reference a2
.
To explain my thoughts on the second question,
I thought that all parameters need a name when a function or method is declared (I may of course be wrong).
If my overloaded copy assignment block was written hypothetically as:
Base &lhs operator = (const Base &rhs)
am I right in saying that lhs
is referring to a2
but as we don't do anything with lhs
due to the implied this
parameter, we don't need to give a parameter name following the ampersand before the operator?
How does this copy assignment operator work?
Redacted:
Base& operator=(Base const& rhs) {
cout << "Base operator=\n";
value = rhs.value;
return *this;
}
The assignment operator is just a function call. In this particular class's case, the compiler will synthesize one that does the right thing, but if you want the cout
side-effect for educational purposes you've done the right thing.
You could also call it in a method function style:
b.operator=(b1);
The b = b1;
is just syntactic sugar for the above.
The assignment operator should be self-assignment safe. But general guidance is to make it safe without checking for the self-assignment case explicitly, which is "bad" because it optimizes for the pathological case.
In your implementation, it is safe without the self-assignment check.
I prefer specifying the qualifier in Base const&
order rather than const Base&
order, because the general rule is "the qualifier always binds to the thing to its immediate left", and the exception to the general rule is "...unless the qualifier comes first, in which case it then binds to the thing to its immediate right." That becomes a problem when people have the grasped the exception to the rule, but not the general rule, and then have troubles parsing Base*const*
in their heads.
Does the reference before the operator keyword need a parameter name?
It's name is *this
. It is a return type, not a parameter, so it does not have a parameter name.
Some people have troubles with "Why does C++ use this
as a pointer to itself, rather than as a reference to itself."
It is a historical anomaly from the evolution of C++. Originally, there was a this
pointer, and references had not been added to the language yet.
With 20/20 hindsight, this
would have been a reference. But that ship has sailed.
In my own code, only to help make it more legible, I'll do:
auto& self = *this;
self[i] = 5;
...rather than the more confusing (imo)...
(*this)[i] = 5;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.