关于重载 -> 运算符的说明



我试图了解重载 -> 运算符的工作原理。我有以下课程

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*。通常当我有指针时,我需要使用->运算符或顺从运算符来访问对象。 根据该逻辑,要访问Message对象的可验证m_text,代码应编写如下

(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->()

正如标准所述,[over.ref]/1

表达式x->m被解释为T类型的类对象x(x.operator->())->m(如果存在T::operator->()并且运算符被重载解析机制选为最佳匹配函数)

这意味着messageWrapper->m_text(messageWrapper.operator->())->m_text的语法糖。您可以显式应用后一种样式,但前一种样式更有效。重载operator->使得像使用原始指针一样使用类成为可能,这就是像std::unique_ptrstd::shared_ptr这样的智能指针的工作方式。

标准说:

13.5.6 类成员访问

表达式x->m被解释为类的(x.operator->())->m类型为T的对象x(如果存在T::operator->()并且运算符是 被过载分辨率选为最佳匹配功能 机制

> -> 是一个二元运算符,它使用这两个参数工作,只要它不是指针,它就会继续解析左侧。

也就是说,在调用 Wrapper2::operator ->() 之后的以下代码中,编译器看到返回类型是引用并调用 Wrapper1::operator ->,只有这样调用才会产生指针,并且针对 RealType 解析"m"。

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

运算符 -> 必须返回一个指针,当使用它时,返回值会自动取消引用,因此您不必自己添加第二个 ->

最新更新