我有一个项目,希望我在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);
}
}
答案 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后返回其存储位置的地址。第二个调用返回相同的地址,现在返回您输入的向量。