0

再次阅读 C++ Primer 5 ed。由 lipmann 现在我已经阅读了有关成员访问运算符重载的信息。一切对我来说都很清楚,除了:

struct A
{
    int& operator* () {return *p;}
    void foo()const{cout << "A::foo()\n";}
    int* p = new int(5);
};

struct B
{
    A& operator*(){return a;}
    A* operator->(){return &a;}
    A a{};
};

struct C
{
    B& operator*(){return b;}
    B& operator->(){return b;}
    B b{};
};


int main()
{

    C c;
    //cout << *c << endl; // error.
    c->foo(); // works

}
  • 我学到的是箭头运算符可以重载,并且必须是成员函数。如果我看到 main 中这样的表达式,c->foo()我可以认为它c是一个内置指针,指向一个类类型的对象,该类类型的成员函数称为foofetch 它。或者(如 main 中的情况)c是定义了自己的类类型的对象->。因此,因为c这是一个表达式调用c箭头运算符的对象,该对象返回一个类B类型的对象,该对象本身调用其箭头运算符,直到它返回B对象,该对象->返回一个指向对象的内置指针A,在这种情况下,它被取消引用并且结果对象用于获取foo()功能。所以它递归地调用自己,直到返回一个内置指针并且该指针必须指向一个具有该提取成员的对象。

  • 我不明白的是:为什么取消引用运算符的工作方式不同?那么为什么解引用只要返回一个定义了解引用操作符的对象c就不会调用*of等操作符呢?b

  • 请不要争论内存泄漏,A目的是为了简洁。

4

2 回答 2

2

这就是->(成员访问)和*(间接)的定义方式。

正如您所指出的,->它将递归调用->它返回的任何内容,直到它解析为指针。此时,您可以使用指针做您想做的事情。

*操作员根本没有被定义为以这种方式工作。无论返回什么,都没有递归调用*

在您的情况下,您可以foo使用间接,但您必须手动执行此操作,如下所示:

(**c).foo();

另请注意,您的特定示例无法编译,因为*c返回对 type 对象的引用,该对象B没有operator<<为它定义。

于 2020-04-19T19:10:46.950 回答
-1

原因是解引用运算符本质上是一元的(返回引用),因此它可以像任何其他运算符一样被重载。并且可以递归使用,如果需要,只需再次应用即可。

OTOH, -> 更像是一个二元运算符......但它右边的东西不是 value 而是name。这个名字必须在某个地方查到。所以编译器肯定需要一个对象。因此运算符被定义为一元的。但它不用作一元,因此如果需要,您可以再次应用它。所以它被定义为另一种方式:您可以依赖递归应用程序,或者通过返回原始指针来“选择退出”它。

免责声明:这就是我的看法。

于 2020-04-19T19:30:24.993 回答