【问题标题】:How does dereference operator (*) work when overloaded as a member function of a class?当作为类的成员函数重载时,解引用运算符 (*) 如何工作?
【发布时间】:2017-03-15 05:41:48
【问题描述】:

当我在operator overloading 上查找书籍和堆栈溢出文章时,我发现了以下内容:

当重载运算符是成员函数时, this 绑定到 左操作数。成员运算符函数少一个(显式) 参数比操作数的数量。

(Addison Wesley,C++ 入门)

所以我的问题是,由于*(取消引用)运算符没有任何左操作数,它如何获取其参数(即对象本身或this)?

【问题讨论】:

  • 我没有找到任何可靠的来源表明重载的一元运算符成员函数将在需要时将右手操作数作为隐式参数。
  • 它是一个一元运算符,它对跟随它的值进行操作
  • 作为一个附加问题,如果将重载的 * 运算符定义为非成员函数与成员函数,它的使用方式会有什么不同吗?

标签: c++ operator-overloading smart-pointers dereference template-function


【解决方案1】:

对于所有前缀一元运算符,它对它后面的操作数进行操作。

作为一个附加问题,如果重载的 * 运算符被定义为非成员函数与成员函数,那么它的使用方式会有什么不同

在大多数情况下,不,除了非成员函数不能访问该类的私有成员并且如果成员函数和非成员函数都存在,编译器需要使用overload resolution来选择更高的等级函数,如果没有更好的函数,就是模棱两可的调用,见ADL

对于可靠的来源,您可以查看operator overloading,或者更好的是,标准 C++ 中的第 13.5.1 [over.unary] 节:

前缀一元运算符应由不带参数的非静态成员函数(9.3)实现或 具有一个参数的非成员函数。因此,对于任何前缀一元运算符@,@x 可以被解释 作为 x.operator@() 或 operator@(x)。如果两种形式的运算符函数都已声明,则 13.3.1.2 中的规则确定使用哪种解释(如果有)。关于后缀的解释见 13.5.7 一元运算符 ++ 和 --。 2 同一运算符的一元和二元形式被认为具有相同的名称。 [注:因此, 一元运算符可以在封闭范围内隐藏二元运算符,反之亦然。 -结尾 注意]

同时有成员和非成员的选择见13.3.1.2 [over.match.oper]

【讨论】:

    【解决方案2】:

    前缀* 作用于它后面的操作数。

    对于用户定义的operator*,表示为成员函数,即this-表达式所引用的对象。

    #include <iostream>
    using namespace std;
    
    struct S
    {
        auto operator*() const -> char const* { return "Hi there!"; }
    };
    
    auto main()
        -> int
    { cout << *S() << endl; }
    

    结果:

    你好呀!

    【讨论】:

    • 作为一个附加问题,如果将重载的 * 运算符定义为非成员函数与成员函数,它的使用方式会有什么不同吗?
    • @sushrut619:这取决于它是如何定义的。要模拟const 成员函数,它应该通过值或引用const 来获取其参数。否则无法在 const 参数上调用。
    【解决方案3】:

    解引用运算符的工作方式与重载运算符和普通运算符的工作方式完全相同。

    int foo(int *p)
    {
         return *p;
    }
    

    在语句return *p; 中,解引用运算符适用于指针p。它在右侧传递给它:

    作为重载运算符,它的工作方式相同。

    class bar {
    
         int *some_internal_ptr;
    
    public:
         int operator*() const {
              return *some_internal_ptr;
         }
    
         // Other class members and methods...
    };
    
    int foo(bar p)
    {
         return *p;
    }
    

    * 运算符的右侧是具有 operator*` 成员的类时,它将作为类的重载方法调用,与任何其他成员没有什么不同,以解决取消引用。

    这是因为用法相同,这就是为什么许多 C++ 库算法与指针或 C++ 库运算符同样适用的原因。例如,std::copy() 可以按如下方式实现(我正在删减一些与此处无关的不相关的复杂性):

    template<typename iter_type>
    iter_type copy(iter_type b, iter_type e, iter_type t)
    {
        while (b != e)
        {
           *t=*b;
           ++t;
           ++b;
        }
        return t;
    }
    

    您可以将本机指针传递给std::copy,或者传递像迭代器这样的类,使用重载的* 运算符,因为重载的* 运算符使用与普通* 运算符相同的语法,所以算法也适用于重载运算符。

    【讨论】:

      猜你喜欢
      • 2012-02-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多