我试图了解重载->运算符的工作方式。我有以下课程
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();
}
MessageWrapper
类的->
运算符被重载以返回Message*
。
因此,在主方法中,当我调用messageWrapper->
时,它返回的是Message*
。通常,当我有一个指针时,我需要使用->
运算符或deference运算符来访问该对象。
根据该逻辑,要访问m_text
对象的Message
验证,代码应如下编写
(messageWrapper->) // this returns a pointer to Message. so to access the object, I should write as
(messageWrapper->)->m_text = "PQR"
或
*(messageWrapper->).m_Text = "PQR"
但这不能那样工作,我需要将其称为
messageWrapper->m_text = "PQR";
我不明白这里的逻辑。我可以对此进行澄清。
==============
一些其他说明:
在主要方法中,我看到以下两种方法具有相同的作用
messageWrapper.operator->()->m_text = "JKH";
messageWrapper->m_text = "JKH";
这是否意味着运营商->
的工作方式不同于其他运营商
messageWrapper->
等效于(messageWrapper.operator->())->
而不是messageWrapper.operator->()
,就像其他运算符一样。
答案 0 :(得分:9)
标准状态为[over.ref]/1
如果类型为{{1}的类对象
x->m
(如果存在(x.operator->())->m
并且如果选择了最佳运算符,则表达式x
被解释为T
通过重载解析机制实现匹配功能
这意味着T::operator->()
是messageWrapper->m_text
的语法糖。您可以显式地应用后一种样式,但是前一种样式更有效。重载的(messageWrapper.operator->())->m_text
使得可以像原始指针一样使用该类,这就是operator->
和std::unique_ptr
这样的智能指针的工作方式。
答案 1 :(得分:5)
标准说:
13.5.6类成员访问权限
表达式
x->m
被解释为类的(x.operator->())->m
类型x
的对象T
(如果存在T::operator->()
并且操作符为 过载分辨率选择为最佳匹配函数 机制
答案 2 :(得分:3)
->是二进制运算符,它同时使用两个参数,并且只要不是指针,都将继续解析左侧。
也就是说,在下面的代码中,在调用Wrapper2 :: operator->()之后,编译器会看到返回类型是引用,并调用Wrapper1 :: operator->,然后调用才会产生指针而'm'是针对RealType解析的。
struct RealType
{
int m;
};
class Wrapper1 {
RealType rt;
public:
RealType * operator ->() { return &rt; }
};
class Wrapper2 {
Wrapper1 w1;
public:
Wrapper1 & operator->() { return w1; }
};
int main()
{
Wrapper2 w;
w->m = 1;
};
答案 3 :(得分:2)
运算符->必须返回一个指针,使用该指针时,返回值将自动取消引用,因此您不必自己添加第二个->