方括号[]运算符重载c ++

时间:2017-03-23 11:47:46

标签: c++ operator-overloading

我有一个项目,希望我在c ++(大学项目)中创建一个BigNum类 它说要重载操作员支架以获取和设置 但问题是如果集合无效,我们应该抛出一个无效就像

的异常
BigNum a;
a[i]=11;//it is invalid because its >9

在搜索中我发现了如何使设置工作

C++ : Overload bracket operators [] to get and set

但是我没有找到如何在c#中管理设置操作,你很容易就可以管理设定值在c ++中它的等价物

在C#中说清楚我们可以说

public int this[int key]
{
    set
    {
        if(value<0||value>9)throw new Exception();
        SetValue(key,value);
    }
}

3 个答案:

答案 0 :(得分:1)

你可以定义一个wapper,比如NumWapper,它包含了BigNum元素的引用。 BigNum的operator=按值返回包装器。

a[i]=11;

就像NumWrapper x(...); x = 11。现在,您可以在operator=的{​​{1}}中执行这些检查。

NumWrapper

在NumWrapper中,重载一些运算符,例如:

class BigNum {
 public:
  NumWrapper operator[](size_t index) {
    return NumWrapper(array_[index]);
  }

  int operator[](size_t index) const {
    return array_[index];
  }
};

您还可以将NumWrapper的副本和移动构造函数声明为私有,并将BigNum作为他的朋友,以防止用户代码复制您的包装器。如果你这样做,这样的代码class NumWrapper { public: NumWrapper(int &x) : ref_(x) {} NumWrapper(const NumWrapper &other) : ref_(other.ref_) {} NumWrapper &operator=(const NumWrapper &other); int operator=(int x); operator int(); private: int &ref_; }; 将无法编译,而用户代码仍然可以通过auto x = a[i]复制包装的值(尽管有些冗长)。

auto x = static_cast<T>(a[i])

似乎我们很好。

这也是另一种方法:将元素存储为用户定义的类,比如auto &x = a[i]; // not compiling const auto &x = a[i]; // dangerous anyway, can't prevent. 。我们现在将类BigNum定义为:

BigNumberElement

我们需要为BigNumberElement声明一个完整的集合运算符,例如比较(也可以通过转换完成)​​,赋值,构造函数等,以便于使用。

class BigNum { // some code private: BigNumberElement array_[10]; } 现在将获得BigNumberElement的副本,这在大多数情况下都可以。只有分配它有时会抛出异常并引入一些运行时开销。但是我们仍然可以写auto x = a[i](虽然......但仍然冗长)。据我所知,意外的编译时错误消息比意外的运行时异常更好。

我们也可以使BigNumberElement不可复制/可移动......但是它会与第一种方法相同。 (如果任何成员函数返回auto x = static_cast<T>(a[i]),则会返回意外的运行时异常。)

答案 1 :(得分:0)

以下定义了从foo::setter返回的类型operator[],并重载其operator=以分配值,但如果该值不在允许的范围内则抛出。

class foo
{
  int data[10];
public:
  void set(int index, int value)
  {
    if(value<0 || value>9)
      throw std::runtime_error("foo::set(): value "+std::to_string(value)+" is not valid");
    if(index<0 || index>9)
      throw std::runtime_error("foo::set(): index "+std::to_string(index)+" is not valid");
    data[index] = value;
  }
  struct setter {
    foo &obj;
    size_t index;
    setter&operator=(int value)
    {
      obj.set(index,value);
      return*this;
    }
    setter(foo&o, int i)
    : obj(o), index(i) {}
  };
  int operator[](int index) const // getter
  { return data[index]; }
  setter operator[](int index) // setter
  { return {*this,index}; }
};

答案 2 :(得分:0)

如果您要执行的操作是重载[],则可以在其中输入信息(例如dict)或映射(例如dict [key] = val)。答案实际上很简单:

让我们说您要加载std :: string作为键,并加载std :: vector作为值。 并假设您有一个unordered_map作为您要向其传递信息的基础结构

std::unordered_map<std::string, std::vector<double>> myMap;

在您自己的班级中,您具有以下定义:

class MyClass{
    private:
        std::unordered_map<std::string, std::vector<double>> myMap;
    public:
        std::vector<double>& operator [] (std::string key) {
        return myMap[key];
    }

}

现在,当您要加载对象时,只需执行以下操作:

int main() {

    std::vector<double> x;
    x.push_back(10.0);
    x.push_back(20.0);
    x.push_back(30.0);
    x.push_back(40.0);
    
    MyClass myClass;
    myClass["hello world"] = x;

    double x = myClass["hello world"][0]; //returns 10.0
}

重载的[]返回对该向量的存储位置的引用。因此,当您第一次调用它时,它将为您的向量分配= x后返回其存储位置的地址。第二个调用返回相同的地址,现在返回您输入的向量。