当尝试捕获时C++返回值

当尝试捕获时C++返回值,c++,exception,return-value,try-catch,C++,Exception,Return Value,Try Catch,嗨,当WARANING控件到达非空函数的末尾时,我应该怎么做? 我的重载操作符有try-and-catch并返回*this;在try范围内 我使用的是Eclipse,G++是编译器,UBUNTU linux NNmatrix & operator*=(const NNmatrix<T> &mtrxB) { // A=2*3 B=3*4 return C=2*4 const UINT aRows = th

嗨,当WARANING控件到达非空函数的末尾时,我应该怎么做? 我的重载操作符有try-and-catch并返回*this;在try范围内

我使用的是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;
            }
        }

警告是指函数外有一个非异常控制路径没有return语句


您的捕获范围是否有类似的返回?如果它不应该返回,您可能需要重新调用。

警告指的是,函数外有一个非异常控制路径没有返回语句


您的捕获范围是否有类似的返回?如果它不应该返回,您可能希望重新执行。

如果函数返回除void以外的任何内容,您需要确保所有代码路径都返回一个值

如果您在内部处理此函数的异常而不重新引用,为什么不直接返回*this;在函数的末尾,而不是从try块内部


EDIT:per@Mark在下面的注释中指出,只要移动return语句,就会隐藏一个在请求的操作上下文中是致命的错误,并使库在该过程中相当不可靠。最好传播异常,如果这是处理就地乘法错误的方法,这似乎是一种合理的方法。

如果函数返回的不是void,则需要确保所有代码路径都返回一个值

如果您在内部处理此函数的异常而不重新引用,为什么不直接返回*this;在函数的末尾,而不是从try块内部


EDIT:per@Mark在下面的注释中指出,只要移动return语句,就会隐藏一个在请求的操作上下文中是致命的错误,并使库在该过程中相当不可靠。最好传播异常,如果这是处理就地乘法错误的方法,这似乎是一种合理的方法。

基本上,我知道您的运算符看起来像:

Object& operator=(Object const& rhs)
{
  try
  {
    // something
    return *this;
  }
  catch(std::exception& e)
  {
    std::cerr << e.what() << '\n';
  }
}
现在的问题是,当抛出并捕获异常时,返回哪个值? 回答是,您不返回任何内容,那么编译器应该做什么呢

您需要决定在捕获路径上执行什么操作:

要么抛出相同的异常,要么抛出另一个你喜欢的异常 或者返回*如果你能忍受这个错误 但是对于赋值运算符,我强烈建议您不要抛出任何异常,这与盲目应用try/catch块有细微的区别

编辑:

解决问题的一种更简单的方法是先检查,如果异常不匹配,则抛出异常而不修改任何内容,然后继续编写代码而不必担心异常的发生

这是在异常领域开发的一般方式:先做可能抛出的事情,然后你就不必担心异常在这里或那里突然出现


还有,作为一句话,你不敢扔坏东西!你不能盲目地选择一个现有的异常并为你自己的方便而使用它:一个异常类型意味着系统不能满足你的内存请求,而不是一些矩阵实现出了问题。

基本上我知道你的操作符看起来像:

Object& operator=(Object const& rhs)
{
  try
  {
    // something
    return *this;
  }
  catch(std::exception& e)
  {
    std::cerr << e.what() << '\n';
  }
}
现在的问题是,当抛出并捕获异常时,返回哪个值? 回答是,您不返回任何内容,那么编译器应该做什么呢

您需要决定在捕获路径上执行什么操作:

要么抛出相同的异常,要么抛出另一个你喜欢的异常 或者返回*如果你能忍受这个错误 但是对于赋值运算符,我强烈建议您不要抛出任何异常,这与盲目应用try/catch块有细微的区别

编辑:

解决问题的一种更简单的方法是先检查,如果异常不匹配,则抛出异常而不修改任何内容,然后继续编写代码而不必担心异常的发生

这是在异常领域开发的一般方式:先做可能抛出的事情,然后你就不必担心异常在这里或那里突然出现


还有,作为一句话,你不敢扔坏东西!您不能盲目地选择一个现有的异常并为自己的方便而使用它:一个异常类型带有含义且错误分配意味着系统无法满足您的内存请求,而不是某些矩阵实现出现错误。

您的问题的解决方案是:

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;
        }

您的问题的解决方案是:

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;
        }

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

想想ab 用户将如何调用它。看起来您希望他们能够享受以下便利:

NNMatrix<int> matrixA; // Obviously with real assignments...
NNMatrix<int> matrixB;
matrixA *= matrixB;
if(!matrixA.MultiplyBy(matrixB)) {
   // Handle runtime error
}
现在,有人会把你的每一个电话都打包成试一试的机会有多大?即使他们这样做了,也不比替代方案更干净,替代方案使用普通成员函数,如:

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

这是更好的,因为如果他们忘记检查退货,这将永远不会导致崩溃。从公共API可以明显看出,用户需要检查错误,操作要么完全成功,要么失败。不可否认,它仍然不漂亮,如果用户没有“如果”逻辑,他也不会得到他所期望的,但至少他已经得到了警告。据我所知,如果您真的必须在编译时支持具有未知行数和列数的矩阵,这是您能做的最好的事情。

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

想一想用户将如何称呼它。看起来您希望他们能够享受以下便利:

NNMatrix<int> matrixA; // Obviously with real assignments...
NNMatrix<int> matrixB;
matrixA *= matrixB;
if(!matrixA.MultiplyBy(matrixB)) {
   // Handle runtime error
}
现在,有人会把你的每一个电话都打包成试一试的机会有多大?即使他们这样做了,也不比替代方案更干净,替代方案使用普通成员函数,如:

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


这是更好的,因为如果他们忘记检查退货,这将永远不会导致崩溃。从公共API可以明显看出,用户需要检查错误,操作要么完全成功,要么失败。不可否认,它仍然不漂亮,如果用户没有“如果”逻辑,他也不会得到他所期望的,但至少他已经得到了警告。据我所知,如果您真的必须在编译时支持具有未知行数和列数的矩阵,那么这是您所能做的最好的事情。

请发布您的代码以及您使用的编译器。您应该修复警告。现在,您是否有一个示例来演示您的问题?请发布您的代码,我从您的问题中对问题只有一个模糊的概念。您是否在catch范围内返回smth?好的,在这里,提前谢谢。请发布您的代码和您使用的编译器。您应该修复警告。现在,你有一个例子来说明你的问题吗?请发布你的代码,我从你的问题中得到的只是一个模糊的概念。你是否在catch范围内返回smth?好的,在这里,提前谢谢。你可以详细说明最后一段吗?这是否意味着我不应该把一个例外放在首位?你能详细说明最后一段吗?这是否意味着我不应该把一个异常放在第一位?将返回放在函数的末尾只是隐藏了一个事实,即存在一些您根本无法进行矩阵乘法的输入。如果您正常返回,它看起来成功了,但实际上没有。完全禁用catch块并让异常传播出去,这样就可以找到并修复错误代码,不是更好吗?@Mark B-你说得对:我在代码出现之前发布了这篇文章。注意关于异常处理的警告。@Mark和Steve,我注释掉了try,catch。但是,在抛出之后我应该放什么呢???通常,您会抛出一个标准异常,或者抛出一个您自己的自定义异常,该异常派生自那些类中的一个,而不是std::exception。在这种情况下,无效的_参数对我来说似乎是合理的。要记住的主要事情是,定义和测试API的错误以及它的正常返回代码路径和值取决于您。将返回放在函数末尾只是隐藏了一个事实,即存在一些您根本无法进行矩阵乘法的输入。如果您正常返回,它看起来成功了,但实际上没有。完全禁用catch块并让异常传播出去,这样就可以找到并修复错误代码,不是更好吗?@Mark B-你说得对:我在代码出现之前发布了这篇文章。注意关于异常处理的警告。@Mark和Steve,我注释掉了try,catch。但是,在抛出之后我应该放什么呢???通常,您会抛出一个标准异常,或者抛出一个您自己的自定义异常,该异常派生自那些类中的一个,而不是std::exception。在这种情况下,无效的_参数对我来说似乎是合理的。要记住的主要事情是,定义和测试API的错误以及它的正常返回代码路径和值取决于您。