【问题标题】:Using normal and overloaded operator at the same time同时使用普通运算符和重载运算符
【发布时间】:2013-05-14 08:04:22
【问题描述】:

我有一个类,我重载了 [ 运算符以在 main 中使用。但这里的问题是;在另一个函数的类中的某个地方。我想像旧样式一样使用 [ 运算符。我如何同时使用它们或如何修改我重载的 [ 参数?

这里是重载部分。

T &operator[](int i)
{
if (i < 0 || i >= ArithmeticVector<T>::size())
   throw std::string("Out of bounds!"); //throw std::out_of_range;
else
   return data[i];
};

这是我想使用的另一个功能;

friend ArithmeticVector<T> operator /(const ArithmeticVector<T>& v1, const ArithmeticVector<T>& v2 )
{  
/*Do quick size check on vectors before proceeding*/
ArithmeticVector<T> result(v1.size());
   for (unsigned int i = 0; i < result.size(); ++i)
{
   result[i]=v1[i]/v2[i];
}
   return result;
};

我收到类似错误 C2678: binary '[' : no operator found 之类的错误,它采用“const ArithmeticVector”类型的左操作数

问题出在这一行。

result[i]=v1[i]/v2[i];

重载的运算符不喜欢它:/

【问题讨论】:

  • 当你说“问题出在这一行”时,当你在 main 中划分两个向量时会出现错误?
  • @tomislav-maric 是的。当我从friend ArithmeticVector&lt;T&gt; operator /(const ArithmeticVector&lt;T&gt;&amp; v1, const ArithmeticVector&lt;T&gt;&amp; v2 ) 获取const 时,它编译但仍然崩溃。
  • 当它崩溃时会出现什么错误,SIGFPE?
  • @tomislav-maric 未处理的异常错误。我被困在一个常量或非常量元素循环中。如果我删除 const 程序崩溃,如果这次为其他重载添加 const 它不接受。没救了……
  • 您是否尝试在没有优化的情况下并在完全调试模式下编译您的代码?然后,您可以逐步执行程序并查看究竟发生了什么。如果您发布此内容,将更容易找到问题的解决方案,或者您可能会自己找到它..

标签: c++ operator-overloading friend


【解决方案1】:

我不明白,I want to use [] operator like the old style 是什么意思,但你也应该为 const 版本重载 operator[]

const T& operator[](int i) const
{
    // ...
}

v1v2 在这里不可修改,它们不能调用非常量方法。

【讨论】:

  • 当我从friend ArithmeticVector&lt;T&gt; operator /(const ArithmeticVector&lt;T&gt;&amp; v1, const ArithmeticVector&lt;T&gt;&amp; v2 ) 获取 const 时,它编译但仍然崩溃。如果我为 const one 编写一个新方法,它会起作用吗?以及我将如何为同一方法执行 2 次重载?
  • 1) 可能,不,它不应该依赖于 const 限定符。 2)如何?嗯……就写吧?
  • 实际上它有效,但我收到未处理的异常错误,例如我错过了一些常量或做错了什么。我写了这个顺便说一句T *data2;const T&amp; operator[](int i)const { return data2[i]; }
  • 如果您在非常量版本中检查债券,您还应该在 const 版本中检查它(惯用)。要获取更多信息,请尝试使用 try/catch 块捕获异常。
【解决方案2】:

您还需要重载 const 对象的访问运算符,因为表达式 result[i] = v1[1] / v2 [i] 的右上方将计算为:

v1.operator[](i) / v2.operator[](i)

并且 v1 和 v2 都是 const ArithmeticVector&lt;T&gt;&amp; 类型,这意味着编译器将尝试为它们找到 operator[](int) const(它们是常量对象)。当您按照上述答案中的建议重载 const 运算符时,您可以重用 const 运算符中的代码,只需通过丢弃对象的 const 来调用非常量运算符中的运算符。这样您就不必考虑在一个操作员中实现了什么并将其移植到另一个操作员,并且您不必在两个地方调试您的代码。这是您的问题的模型(我没有您的 ArithmeticVector 实现,因此您必须将其部分用于您的东西):

template<typename T>
class ArithmeticVector;

template<typename T>
ArithmeticVector<T> operator / (
    const ArithmeticVector<T>& v1, 
    const ArithmeticVector<T>& v2
);

template<typename T>
class ArithmeticVector 
{
    public:

        // Your declaration
        T& operator[](int i)
        {
            // Casting away constness allows code re-use. 
            return const_cast<ArithmeticVector&>(*this).operator[](i);
        }

        // Const declaration:
        T& operator[](int i) const
        {
            // Put your operator code here. 
        }

        friend ArithmeticVector<T> operator / <> (
            const ArithmeticVector<T>& v1, 
            const ArithmeticVector<T>& v2
        );
};

template<typename T>
ArithmeticVector<T> operator / (
    const ArithmeticVector<T>& v1, 
    const ArithmeticVector<T>& v2
)
{
    //ArithmeticVector<T> result(v1.size());
    ArithmeticVector<T> result;

    result[0]=v1[0]/v2[0];

    return result;
};


int main(int argc, const char *argv[])
{

    ArithmeticVector<int> v1, v2, v3; 

    v1 = v2 / v3;

    return 0;
}

Scott Meyers 有一本很棒的书“Effective C++”,在那里您可以阅读关于对象的常量性和访问运算符的精彩描述。 SO上有一个answer,谈到了这个。

您还需要注意避免浮点异常(被零除)或 SIGFPE,这将在 v3[i] == 0 时发生,您可以通过稳定结果来做到这一点(您会失去准确性):

result[i] = v1[i] / (v2[I] + 1e-15)

或者你引入一个显着减慢除法的测试(比如 if 测试if v2[i] == 0)。

【讨论】:

    猜你喜欢
    • 2012-11-26
    • 2016-02-19
    • 1970-01-01
    • 2015-03-13
    • 2017-12-23
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多