【问题标题】:C++ Why does the automatic re-application of the arrow (->) operator not apply to pointer-to-pointer types?C++ 为什么箭头(->)运算符的自动重新应用不适用于指针到指针类型?
【发布时间】:2018-04-06 22:42:09
【问题描述】:

This question 讨论箭头运算符-> 如何自动重新应用于重载operator->() 的返回值,直到返回的值是原始指针,此时原始指针被取消引用,就像使用@ 987654324@。但是,当一个人希望取消对基值的引用的指针到指针类型时,情况并非如此——他们必须改用(*ptr_to_ptr)->foo()。在我看来,ptr_to_ptr->foo() 的用法是明确的,甚至比在返回原始指针之前自动重新应用 -> 更重要。那么,这个决定背后的原因是什么?

最小的工作示例:

#include <iostream>

struct Dog {
    void bark() { std::cout << "woof!" << std::endl; }
};

struct DogWalker {
    Dog* dog;
    Dog* operator->() {
        return dog;
    }
};

struct DogOwner {
    DogWalker walker = { new Dog() };
    DogWalker operator->() {
        return walker;
    }
};

void main()
{
    DogOwner owner;
    owner->bark(); // works, prints "woof"

    Dog** ptr_to_ptr = new Dog*;
    *ptr_to_ptr = new Dog;
    (**ptr_to_ptr).bark(); // works
    (*ptr_to_ptr)->bark(); // works
    //ptr_to_ptr->bark(); // ERROR
    //C2227: left of '->bark' must point to class/struct/union/generic type
}

【问题讨论】:

  • 因为它没有 - 这就是定义语言的方式。
  • 您是否要求标准委员会讨论该语言功能的提议和拒绝?如果没有怎么办? -&gt; 比您与之比较的 operator-&gt;() 要老得多。
  • @DrewDormann 我想我会的。我试图找到一些关于它的讨论但不能,所以我在这里询问是否有人有任何见解。这个站点上还有许多其他问题,它们的答案讨论了为什么某些事情在 c++ 中以它们的方式工作,我认为这里可能有机会进行类似的讨论。您对-&gt;operator-&gt;() 早得多的评论也许是起点 - 我的问题是否可以更好地表述为为什么operator-&gt;() 具有它所做的自动重新应用?
  • @NeilButterworth 显然。但是,类似的操作具有不同的语义是否有一些历史原因?
  • 这样做的目的是允许智能指针类,因此它们重载-&gt;。重复的应用程序允许它们返回其他智能指针。但是指针对指针不是一回事。

标签: c++ language-design


【解决方案1】:

该语言采用了 C 的大部分语义。-&gt; 运算符在应用于指针类型时仅在指针指向非数组复合类型时才有效。由于 C 没有类,因此 C++ 为重载的 -&gt; 定义了自己的语义,这对于智能指针用例是有意义的。

您可以使用辅助类实现您想要的行为。

template <typename T>
struct Unwrap {
    T *p_;
    Unwrap (T *p = 0) : p_(p) {}
    T * operator -> () const { return p_; }
};

template <typename T>
struct Unwrap<T *> {
    T **p_;
    Unwrap (T **p = 0) : p_(p) {}
    Unwrap<T> operator -> () const { return *p_; }
};

template <typename T>
Unwrap<T> make_unwrap (T *p) { return p; }

然后你可以像这样使用它:

struct foo {
    void bar () { std::cout << "Hello\n"; }
};

int main () {
    foo p;
    auto pp = &p;
    auto ppp = &pp;
    auto pppp = make_unwrap(&ppp);

    pppp->bar();
}

Try it online!

【讨论】:

  • 所以本质上,这是因为指针上的-&gt; 来自C(所以不能/不应该改变),但是C++ 引入了重载的operator-&gt;()。很高兴知道,谢谢,有用的例子!
猜你喜欢
  • 2019-04-11
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多