I am trying to understand how overloading -> operator works. I have the following classes
class Message {
public:
Message(string message) :m_text(message) {}
void printText() {
cout << "text is " << m_text << endl;
}
string m_text;
};
class MessagePointerWrapper
{
public:
MessagePointerWrapper(string message) {
m_message = std::make_unique<Message>(message);
}
Message* operator->() {
return m_message.get();
}
std::unique_ptr<Message> m_message;
};
int main(int argc, char** argv)
{
MessagePointerWrapper messageWrapper = MessagePointerWrapper("Hello World");
messageWrapper.m_message->printText();
messageWrapper->m_text = "PQR";
messageWrapper.m_message->printText();
}
The MessageWrapper
class's ->
operator is overloaded to return a Message*
.
So in the main method when I call messageWrapper->
what it returns is a Message*
. Usually when I have a pointer, I need to use ->
operator or the deference operator to access the object.
According to that logic, to access the m_text
veriable of the Message
object, the code should be written as below
(messageWrapper->) // this returns a pointer to Message. so to access the object, I should write as
(messageWrapper->)->m_text = "PQR"
or
*(messageWrapper->).m_Text = "PQR"
but this does not work that way and I need to call it as
messageWrapper->m_text = "PQR";
I don't understand the logic here. Can I get a clarification on this please.
==============
Some further notes :
In the main method I saw the below two methods do the same thing
messageWrapper.operator->()->m_text = "JKH";
messageWrapper->m_text = "JKH";
does it mean the operator ->
works different from other operators where it means
messageWrapper->
is equivalent to (messageWrapper.operator->())->
and not messageWrapper.operator->()
as is the case of other operators.
The class member access operator (->) can be overloaded but it is bit trickier. It is defined to give a class type a "pointer-like" behavior. The operator -> must be a member function.
The operator-> has special semantics in the language in that, when overloaded, it reapplies itself to the result. While the rest of the operators are applied only once, operator-> will be applied by the compiler as many times as needed to get to a raw pointer and once more to access the memory referred by that pointer.
Most can be overloaded. The only C operators that can't be are . and ?: (and sizeof , which is technically an operator). C++ adds a few of its own operators, most of which can be overloaded except :: and .
As the standard states, [over.ref]/1
An expression
x->m
is interpreted as(x.operator->())->m
for a class objectx
of typeT
ifT::operator->()
exists and if the operator is selected as the best match function by the overload resolution mechanism
That means messageWrapper->m_text
is a syntax sugar of (messageWrapper.operator->())->m_text
. You can apply the latter style explicitly, but the former is more efficient. The overloaded operator->
makes it possible to use the class like raw pointers, and that's how smart pointers like std::unique_ptr
and std::shared_ptr
work.
The standard says :
13.5.6 Class member access
An expression
x->m
is interpreted as(x.operator->())->m
for a class objectx
of typeT
ifT::operator->()
exists and if the operator is selected as the best match function by the overload resolution mechanism
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With