C++ 运算符 []

C++ operator []

我正在尝试实现运算符 [],它一次用于 Set,一次用于 Get,我需要区分这两种情况,对于 get,我需要抛出一个异常,如果返回值等于-1;而在 Set 的情况下,我只是覆盖值。 苹果[2] = X; y=苹果[2];

我不知道如何区分这两种模式,我的函数签名是:

   double& Security::operator[](QuarterType index){
    if(index<0 || index>MAX_QUATERS){
        throw ListExceptions::QuarterOutOfBound();
    }
    return evaluation[index].getValueAddress();
   }

"Get" 版本可以引用 const 并标记为 const:

const double& Security::operator[](QuarterType index) const

"Set"版本可以写成你现在的版本:

double& Security::operator[](QuarterType index)

有时当您需要强制调用 const 版本时,您可以 const_cast 您的对象为 const 类型。 (但是不要反过来做:如果原始对象是 const,则丢弃 const-ness 的行为是未定义的)。

但我个人认为这不必要地复杂化。摆脱运算符重载并编写单独的 getset 函数可能更实用。您 可以 QuarterType class 做一些事情:也许将特征系统注入其中,允许函数相应地处理特定的 QuarterType 实例。但这可能并不比使用不同名称的单独函数更好。

(如果 QuarterType 是一个大对象,则考虑传递 const QuarterType&。这将防止获取值副本。)

查看 cppreference.com 上的 operator overloading 篇文章。 数组下标运算符部分准确解释了您的需求:

User-defined classes that provide array-like access that allows both reading and writing typically define two overloads for operator[]: const and non-const variants:

struct T {
          value_t& operator[](std::size_t idx)       { return mVector[idx]; };
    const value_t& operator[](std::size_t idx) const { return mVector[idx]; };
};

If the value type is known to be a built-in type, the const variant should return by value.

(continued)

因此,您应该定义 double Security::operator[](QuarterType index) const,而不是 const double& Security::operator[](QuarterType index) const

I am trying to implement the operator [] that is to be used once for Set and once as Get

无法完成。您可以使用不同的签名(即 const 和非 const 版本)实现多个版本的运算符,但它们不会被正确调用。

相反,请考虑使用您需要的功能实现 set 和 get 函数。

您可以 return 来自 [] 运算符的代理对象,该对象具有针对目标类型的隐式转换 operator doubleoperator =。如果对话运算符被调用并且你的值为-1你抛出,如果赋值被调用你赋值。

与 python 或 C# 等语言不同,C++ 不为其运算符提供获取和设置模式。因此,您必须编写 operator[] 以便它 return 是一个在您希望它被使用的任何上下文中使用时做正确事情的对象,这通常意味着引用。

注意我说的是通常;您还可以执行其他操作,例如 return 具有以下成员的 class 实例:

struct proxy
{
    operator double() const;
    void operator=(double x);
};

如果在需要双精度的上下文中使用此代理对象,它将调用隐式转换运算符,该运算符是为执行您的 get 操作而实现的。同样,如果有人给代理对象赋值,它会调用赋值运算符,它被实现来做你的集合操作。

(请注意,代理可能需要引用您的 Security 对象)

不过,这种方法并非没有困难;由于您的 return 值不是 doubledouble& 或类似类型,它可能会导致与重载解析的混淆,尤其是模板函数,并且在与 [= 一起使用时会造成很多混淆15=]。而且您的代理对象甚至不能在需要 double&!

的上下文中使用

因此,这是万不得已的方法,当您被逼到角落并且必须根据假装的operator[]进行访问时与 double 一起工作。在你诉诸于此之前,你真的应该寻求其他选择,例如:

  • 重新设计您的程序,以便索引 Security 对象可以 return 引用 double,而不需要更复杂的获取和设置操作。 (例如,更改不变量以便没有异常数据,或者在其他地方进行错误处理)
  • 满足于使用专用的获取和设置操作。甚至给他们起更复杂的名字,以反映他们正在做的事情比人们通常认为的索引集合更重要。
  • 重新设计 API 以便用户期望从 operator[] 获得具有各种重要行为的代理对象,而不是期望使用 operator[] 到 read/write double 个对象。

C++ 不容易区分

appple[2] = X; 
y=apple[2];

最常见的解决方案是return一个代理对象:

struct AppleProxy
{
   Security & obj; 
   unsigned index;

   AppleProxy(Security &, unsigned) : ... {}

   operator double()   // your getter
   {
      return obj.GetAt(index);
   }

   operator=(double rhs)
   {
      obj.SetAt(index, rhs);
   }
}

AppleProxy operator[](unsigned index) { return AppleProxy(*this, index); }

Proxy 需要特别注意细节,我省略了 const 正确性、生命周期管理、获取地址 (double & x = apple[2]; x = 17;) 等

由于陷阱,我倾向于避免它们。