【问题标题】:Overloading the subscript operator "[ ]" in the l-value and r-value cases在左值和右值情况下重载下标运算符“[ ]”
【发布时间】:2011-04-20 17:52:25
【问题描述】:

我在班级 Interval 中重载了 [] 运算符以返回 分钟

但我不确定如何使用 [] 运算符为 minutessecond 赋值。

例如:我可以用这个语句

cout << a[1] << "min and " << a[0] << "sec" << endl;

但我想重载 [] 运算符,以便我什至可以使用将值分配给分钟或秒

a[1] = 5;
a[0] = 10;

我的代码:

#include <iostream>

using namespace std;

class Interval
{

public:

    long minutes;
    long seconds;

    Interval(long m, long s)
    {
        minutes = m + s / 60;
        seconds = s % 60;
    }

    void Print() const
    {
        cout << minutes << ':' << seconds << endl;
    }

    long operator[](int index) const
    {
        if(index == 0)
            return seconds;

        return minutes;
    }

};

int main(void)
{
    Interval a(5, 75);
    a.Print();
    cout << endl;

    cout << a[1] << "min and " << a[0] << "sec" << endl;
    cout << endl;

}

我知道我必须将成员变量声明为私有,但我在这里声明为公共只是为了方便。

【问题讨论】:

  • 这似乎是一个糟糕的运算符重载示例。您是否有一些模糊的要求迫使您这样做?否则只是代码混淆。
  • @jalf 我知道这是一个糟糕的例子,但我想在 Object Array 的泛型类中重载 [] 运算符。
  • @jalf: 为什么cpp.sh/4fiz 工作时没有任何编译器错误?编译器不应该抛出错误吗?它不提供任何输出。这个程序到底发生了什么。

标签: c++ operator-overloading subscript-operator


【解决方案1】:

返回对相关成员的引用,而不是其值:

long &operator[](int index)
{
    if (index == 0)
        return seconds;
    else
        return minutes;
}

【讨论】:

    【解决方案2】:

    通过删除 const 并返回引用来更改函数签名:

    long& operator[](int index)
    

    现在您将能够编写如下语句:

    a[0] = 12;
    

    【讨论】:

    • 不要忘记 op[] 的 const 重载。
    • 即不要删除已有的。 添加这个。
    【解决方案3】:

    重载 op[] 以使用硬编码的“索引”值在这里没有意义,实际上您的类定义中已经有了解决方案:

    cout << a.minutes << "min and " << a.seconds << "sec" << endl;
    

    您可以将它们转换为方法而不是公共数据成员,这对于不重载 op[] 是无关紧要的。但是,由于您也需要写访问权限,因此方法的唯一优势是验证(例如检查 0

    struct Interval {
      int minutes() const { return _minutes; }
      void minutes(int n) { _minutes = n; }  // allows negative values, etc.
    
      int seconds() const { return _seconds; }
      void seconds(int n) {
        if (0 <= n and n < 60) {
          _seconds = n;
        }
        else {
          throw std::logic_error("invalid seconds value");
        }
      }
    
      // rest of class definition much like you have it
    
    private:
      int _minutes, _seconds;
    };
    
    // ...
    cout << a.minutes() << "min and " << a.seconds() << "sec" << endl;
    

    【讨论】:

    • 我知道这没有任何意义,但是如果我想使用 [] 运算符赋值我该怎么办。
    • @Searock:另一个答案涵盖了它,但我不会推荐它作为这个问题的解决方案。
    • @Roger Pate +1 我知道这是一个非常愚蠢的例子,但这只是为了清除我的疑问,我的女士告诉我,重载 [] 运算符进行分配是不可能的。
    【解决方案4】:

    通过引用返回以便能够赋值并在赋值运算符的 LHS 上使用它们。

    【讨论】:

    • 我是c++初学者,能举个例子吗?
    • @Searock 抱歉,我正要添加示例。刚刚注意到 Vijay 已经添加了 sn-p。请参考。一般来说,在 C++ 中,如果您希望能够在赋值的 LHS 上使用覆盖的运算符函数返回的值,那么您应该在覆盖的运算符函数中通过引用返回。
    【解决方案5】:

    将方法转换为下面给出的应该这样做:

    long& operator[](int index) 
    

    【讨论】:

      【解决方案6】:

      您的数组索引成员运算符应提供为

      long& operator[](int index);                    // for non const object expressions
      
      long const& operator[](int index) const;        // for const object expressions
      

      【讨论】:

        【解决方案7】:

        为了避免子脚本运算符重载的情况下出现混淆,建议使用constnon-const版本的子脚本运算符。

        long& operator[](int index);  // non-const function returning reference
        
        long const& operator[](int index) const;// const function returning const reference
        

        使用A[1] = 5,您正在尝试修改index 1 处的对象。所以会自动调用非常量版本的子脚本操作符。

        使用cout &lt;&lt; A[1],您不会修改index 1 处的对象。所以会自动调用 const 版本的子脚本操作符。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-12-08
          • 2015-01-28
          • 1970-01-01
          • 2021-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多