【问题标题】:C++ - Overloading [] operators based on the side of assignmentC++ - 基于赋值侧重载 [] 运算符
【发布时间】:2015-07-04 01:13:58
【问题描述】:

我正在尝试用 C++ 编写一个动态数组模板

我目前正在重载 [] 运算符,我想根据它们用于赋值的哪一侧来实现不同的行为。

#include <iostream>
...

template <class T>
T dynamic_array<T>::operator[](int idx) {
    return this->array[idx];
}

template <class T>
T& dynamic_array<T>::operator[](int idx) {
    return this->array[idx];
}

using namespace std;
int main() {
    dynamic_array<int>* temp = new dynamic_array<int>();

    // Uses the T& type since we are explicitly 
    // trying to modify the stored object
    (*temp)[0] = 1;

    // Uses the T type since nothing in the array 
    // should be modified outside the array
    int& b = (*temp)[0]; 

    // For instance...
    b = 4;
    cout<<(*temp)[0]; // Should still be 1
    return 0;
}

由于明显的原因,我在尝试像这样重载时遇到编译器错误。

有没有合适的方法来做到这一点?

到目前为止,我的搜索还没有成功。我看到的任何重载 [] 运算符似乎都接受用户可以在对象之外修改存储的项目。

我已经实现了使用 (instance(int i), update(int i, T obj)) 的方法,但是能够像使用常规数组一样使用这个类会很好。

【问题讨论】:

    标签: c++ operator-overloading


    【解决方案1】:

    你不能只在返回类型上重载。

    提供常量和非常量访问器重载的标准方法是通过this 的常量来区分:

    T       & get()       { return x; }
    const T & get() const { return x; }  // or T get() const;
    

    对于常量版本,您可以返回 const-reference 或按值返回,具体取决于 T 是什么 - const-reference 可能更普遍有用。

    (当然,你可以写operator[](std::size_t i),而不是get()。我只是想保持简短。)


    我不认为这能 100% 达到你的想法,但那是因为你的推理有误:int b = foo()永远 引用任何东西,即使 @ 987654327@ 返回一个(常量或非常量)引用,因为b 被声明为int 类型,而不是int&amp;。实际上,当您说int b = (*temp)[0]; 时,您实际上会调用非常量版本,但这实际上不是问题。 (要获得恒定版本,您必须说 int b = static_cast&lt;const dynamic_array&lt;int&gt; &amp;&gt;(*temp)[0];(*static_cast&lt;const dynamic_array&lt;int&gt; *&gt;(temp))[0] - 但何必这么麻烦。)

    【讨论】:

    • 第二部分写得很好。了解 C++ 类的第一件事是何时发生复制以及何时发生引用传递/复制。
    【解决方案2】:

    Scott Meyers 在一本Effective C++ 书中谈到了这一点。基本上,诀窍是从索引运算符(operator[]()operator[]() const)返回一个临时的 const 或非 const 代理对象,然后为该代理类重载赋值和隐式转换运算符。像这样的:

    template <class T>
    class Array
    {
      public:
        struct proxy {
          T& element;
    
          proxy(T& el) : element(el) {}
    
          operator const T& () const {
            return element; // For use on RHS of assignment
          }
    
          proxy& operator=(const T& rhs) {
            // For use on LHS of assignment
            // Add your logic here
          }
        };
    
        const proxy operator[](int i) const {
          return proxy(a[i]);
        }
    
        proxy operator[](int i) {
          return proxy(a[i]);
        }
    
      private:
         T* a;
    };
    

    我可能有一些细节错误,但我的想法是推迟决定元素在分配的哪一侧,直到实际尝试分配给它。也就是说,您不知道在调用 operator[] 时会做什么,但是当您尝试分配给后续元素引用时,您肯定会这样做。

    【讨论】:

    • 梅耶斯写过它; STL 做到了!以std::vector&lt;bool&gt; 的形式。在阅读 Meyers 的文章(我刚刚读过)之前,我已经从vector&lt;bool&gt; 获得了适当的灵感,实现了我自己的容器。不过,读得很棒,很高兴看到我的想法是正确的。
    猜你喜欢
    • 1970-01-01
    • 2013-03-30
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 2020-07-01
    • 2018-12-27
    • 1970-01-01
    • 2012-04-22
    相关资源
    最近更新 更多