代码之家  ›  专栏  ›  技术社区  ›  Ismail Marmoush

尝试捕获时的c++返回值

  •  1
  • Ismail Marmoush  · 技术社区  · 14 年前

    嗨,当发生警告“控制达到非空函数结束”时,我该怎么办? 我超载的接线员试着抓住 returns *this ; 在尝试范围内。

    我在用Eclipse,G++是编译器,UBUNTU linux

    NNmatrix & operator*=(const NNmatrix<T> &mtrxB)
            {
                // A=2*3 B=3*4  return C=2*4
                const UINT aRows = this->size1();
                const UINT aCols = this->size2();
                const UINT bRows = mtrxB.size1();
                const UINT bCols = mtrxB.size2();
                try
                {
                    // if cols of first(this) matrix == rows of second matrix
                    if (aCols != bRows) throw bad_alloc();
                    const UINT cRows = aRows;// = rows of first matrix
                    const UINT cCols = bCols; // = cols of second matrix
                    NNmatrix mtrxC(cRows, cCols);
                    T val;
                    for (UINT i = 0; i < cRows; i++)
                    {
                        for (UINT j = 0; j < cCols; j++)
                        {
                            val = 0;
                            for (UINT k = 0; k < bRows; k++)
                            {
                                val += this->matrix.at(i).at(k) * mtrxB.getElement(k, j);
                            }
                            mtrxC.setElement(i, j, val);
                        }
                    }
                    *this = mtrxC;
                    mtrxC.clear();
                    return *this;
                }
                catch (exception& e)
                {
                    cout<<"Dimension don't match: ("<<aRows<<","<<aCols<<") ("<<bRows<<","<<bCols<<")"<<endl;
                }
            }
    
    5 回复  |  直到 14 年前
        1
  •  8
  •   Steve Townsend    14 年前

    如果函数返回 void .

    如果您在内部处理此函数的异常而不重新运行,为什么不 return *this; 在函数的末尾,而不是从函数的内部 try 布洛克?

    编辑:根据下面@Mark的注释,简单地移动return语句就隐藏了一个错误,这个错误在请求操作的上下文中是致命的,并且使库在这个过程中相当不可靠。最好传播异常,如果这是处理就地乘法错误的方法(这似乎是一种合理的方法)。

        2
  •  4
  •   BЈовић    14 年前

    解决问题的方法是:

    NNmatrix & operator*=(const NNmatrix<T> &mtrxB)
            {
                // A=2*3 B=3*4  return C=2*4
                const UINT aRows = this->size1();
                const UINT aCols = this->size2();
                const UINT bRows = mtrxB.size1();
                const UINT bCols = mtrxB.size2();
                try
                {
                    // if cols of first(this) matrix == rows of second matrix
                    if (aCols != bRows) throw bad_alloc();
                    const UINT cRows = aRows;// = rows of first matrix
                    const UINT cCols = bCols; // = cols of second matrix
                    NNmatrix mtrxC(cRows, cCols);
                    T val;
                    for (UINT i = 0; i < cRows; i++)
                    {
                        for (UINT j = 0; j < cCols; j++)
                        {
                            val = 0;
                            for (UINT k = 0; k < bRows; k++)
                            {
                                val += this->matrix.at(i).at(k) * mtrxB.getElement(k, j);
                            }
                            mtrxC.setElement(i, j, val);
                        }
                    }
                    *this = mtrxC;
                    mtrxC.clear();
                }
                catch (exception& e)
                {
                    cout<<"Dimension don't match: ("<<aRows<<","<<aCols<<") ("<<bRows<<","<<bCols<<")"<<endl;
                    // let the exception propagate
                    throw;
                }
    
                // always return *this
                return *this;
            }
    
        3
  •  4
  •   Matthieu M.    14 年前

    基本上我知道你的接线员长得像:

    Object& operator=(Object const& rhs)
    {
      try
      {
        // something
        return *this;
      }
      catch(std::exception& e)
      {
        std::cerr << e.what() << '\n';
      }
    }
    

    现在的问题是,当抛出(并捕获)异常时,返回哪个值? 结果是,您不返回任何内容,那么编译器应该怎么做呢?

    你需要决定在捕获路径上做什么:

    • 要么扔东西(也许是同一个例外,或者是你喜欢的另一个)
    • return *this 如果你能忍受这个错误

    但对于赋值运算符,我强烈建议您不要抛出任何异常,这与盲目地应用 try / catch 封锁。

    编辑 :

    解决问题的一个简单方法是先检查, throw 如果你的异常不匹配(没有修改任何内容),那么就继续你的代码,不要担心会发生异常。

    这是在异常区域开发的一种通用方法:先做可能抛出的事情,然后就不必担心异常会到处出现。

    另外,作为评论, 你不敢扔坏球 ! 不能盲目地选择现有的异常并使用它作为自己的便利:异常类型 携带意义 bad_alloc 这意味着系统无法满足您的内存请求,而不是某些矩阵实现出错。

        4
  •  0
  •   lijie    14 年前

    警告是指函数中有一个不具有返回语句的非异常控制路径。

    你的瞄准镜有类似的回报吗?如果它不该回来,你可能会想再拍一次。

        5
  •  0
  •   Zack Yezek    11 年前

    我不知道您的大设计,但作为一般规则,重载运算符根本不应该有运行时故障(例如“=”、“*”,等等,不应该抛出异常)。 这是因为用户希望它们的行为像数字的+和-等。

    想想用户会怎么称呼它。看起来你希望他们有这样的便利:

    NNMatrix<int> matrixA; // Obviously with real assignments...
    NNMatrix<int> matrixB;
    matrixA *= matrixB;
    

    现在,如果您真的需要支持在运行时设置其大小的矩阵,您将有可能失败的加法、减法和乘法操作。我个人不会让实际操作人员超载 ,+,-, =,等等,因为您只能在异常情况下发出错误信号。

    想想看。您要求用户在每次调用矩阵运算符时都具有这样的安全性:

    try {
       matrixA *= matrixB;
    }
    catch(bad_alloc& ba) {
       // Handle runtime error
    }
    

    现在,有没有可能有人会把你的每一个电话都包在一个试听器里?即使他们这样做了,也不会比使用普通成员函数(如:

    bool NNMatrix<T>::MultiplyBy(const NNMatrix<T>& other);
    

    如果返回false并且在维度不匹配时不执行乘法,则会得到与以前相同的行为。现在打电话的人只需要:

    if(!matrixA.MultiplyBy(matrixB)) {
       // Handle runtime error
    }
    

    这是更好的,因为这永远不会造成崩溃,如果他们忘记检查回报。从公共API可以明显看出,用户需要检查错误,操作要么完全成功,要么完全失败。诚然,它仍然不漂亮,如果用户没有“if()”逻辑,就不会得到他期望的结果,但至少他已经收到警告。据我所知,如果在编译时必须支持行和列未知的矩阵,那么这是最好的选择。