Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在C+中以干净的方式处理异常+;_C++_Exception_Coding Style_Readability_Throw - Fatal编程技术网

C++ 如何在C+中以干净的方式处理异常+;

C++ 如何在C+中以干净的方式处理异常+;,c++,exception,coding-style,readability,throw,C++,Exception,Coding Style,Readability,Throw,我的问题是,我正在编写一个程序,它应该是未来可读的,并且该程序有很多异常情况。因此,每当我必须抛出一个异常时,我必须编写10行以上的代码来初始化我的异常类,并将程序中的信息附加到异常类中。例如: MyExceptionClass ex; ex.setErrorMessage("PIN_CANNOT_GO_IN"); ex.setErrorDetails("The pin is asked to go to the state IN while the depth of the r-coordin

我的问题是,我正在编写一个程序,它应该是未来可读的,并且该程序有很多异常情况。因此,每当我必须抛出一个异常时,我必须编写10行以上的代码来初始化我的异常类,并将程序中的信息附加到异常类中。例如:

MyExceptionClass ex;
ex.setErrorMessage("PIN_CANNOT_GO_IN");
ex.setErrorDetails("The pin is asked to go to the state IN while the depth of the r-coordinate does not support it");
ex.setResolutionMessage("Configure your coordinates-file to move first to the correct position before changing the state of the pin");
ex.VariableList().resize(5);
ex.VariableList()[0].push_back("Pin state: ");
ex.VariableList()[0].push_back(ToString(pin.getPinState()));
ex.VariableList()[1].push_back("Pin target state: ");
ex.VariableList()[1].push_back(ToString(coordinatesData[coordinatesIndex].targetPinState));
ex.VariableList()[2].push_back("Current r Value: ");
ex.VariableList()[2].push_back(ToString(EncoderPosition.r));
ex.VariableList()[3].push_back("Current phi Value: ");
ex.VariableList()[3].push_back(ToString(EncoderPosition.phi));
ex.VariableList()[4].push_back("Current z Value: ");
ex.VariableList()[4].push_back(ToString(EncoderPosition.z));

ex.printLog();
ex.writeLog(exceptionLogFilePath.getValue());

throw ex;
所以只有5个变量,我必须写下所有这些。。。 是否有一种有效的方法来包含程序中的所有信息(至少是变量),而不是每次我想抛出异常时都重写所有这些信息


提前感谢。

如果添加到exception类的数据仅用于显示错误消息,则可以使用字符串连接来减少使用的
push_back()
的数量

例如,您可以使用:

ex.VariableList()[0].push_back(string("Pin state: ") + ToString(pin.getPinState());
您甚至可以连接所有其他消息,而不是为每个消息使用单独的索引(1、2、3、4等)

此外,对于每个字段,您可以使用专用的setter方法来提供适当的值。例如:

ex.VariableList()[0].setPinState(ToString(pin.getPinState()));
void MyExceptionClass::setMessage(Pin& pin, CoordinatesData& cd, EncoderPosition& ep) {
    setPinState(ToString(pin.getPinState()));
    // set whatever else you want here
}
然后将
“Pin状态:”
部件移动到打印错误消息的位置


更进一步说,您的异常类可以有一个专用的方法,该方法接受导致错误消息的所有对象,并调用该消息。例如:

ex.VariableList()[0].setPinState(ToString(pin.getPinState()));
void MyExceptionClass::setMessage(Pin& pin, CoordinatesData& cd, EncoderPosition& ep) {
    setPinState(ToString(pin.getPinState()));
    // set whatever else you want here
}
此外,将
ToString()
部分移动到打印消息的任何位置,只需将值存储在exception类中即可。例如,将上面的行更改为(您需要相应地更改签名):


让打印逻辑决定如何将其转换为字符串。另一个优点是,它允许您以不同的格式打印相同的消息。

您可以使用一个公共函数(fill_out_exception_parameters)为通用异常填充VariableList对象,并在您编写的任何新异常类中重复使用它。

我想我已经找到了最干净的方法。请让我听听你的想法

因此,我将所有相关变量封装在一个模板化类中,如下所示(只是一个简单的示例)

类VarBase
{
VarBase();
静态std::向量uu所有参数;
字符串getStringValue()=0;
};
模板
类变量:公共变量库
{
T值;
字符串名;
字符串描述;
toString();
算子T();
字符串getStringValue();
};
VarBase::VarBase()
{
__所有参数。推回(此);
}
VarBase::~VarBase()
{
//句柄从_allParams向量或任何容器中移除
}
模板
std::string Var::getStringValue()
{
std::strings;

我有一个类似的问题:如何用上下文信息丰富异常

Boost提出了一种解决方案:
try/catch
,并在重新刷新之前在
catch
块中对异常进行充实。它确实充实了异常,但不会自动进行充实

我最后想出的解决方案非常简单,基于C++析构函数的强度。但是首先,如何使用它:

void foo(int i) {
    LOG_EX_VAR(i);
    // do something that might throw
}
是的,就是这样,一个宏调用和
i
与函数名、文件名和宏展开所在的行号一起添加到异常上下文中

背后是什么?这是一个神奇的故事

class LogVar {
public:
    LogVar(LogVar const&) = delete;
    LogVar& operator=(LogVar const&) = delete;

    virtual ~LogVar() {}

protected:
    LogVar();
}; // class LogVar

template <typename T>
class LogVarT: public LogVar {
public:
    LogVarT(char const* fc, char const* fl, int l, char const* n, T const& t):
        _function(fc), _filename(fl), _line(l), _name(n), _t(t) {}

    ~LogVar() {
        ContextInterface::AddVariable(_function, _filename, _line, _name, _t);
    }

private:
    char const* _function;
    char const* _filename;
    int _line;

    char const* _name;
    T const& _t;
}; // class LogVarT

template <typename T>
LogVarT make_log_var(char const* fc,
                     char const* fl,
                     int l,
                     char const* n,
                     T const& t)
{
    return LogVarT(fc, fl, l, n, t);
}

#define LOG_EX_VAR(Var_)                                                      \
    LogVar const& BOOST_PP_CAT(_5416454614, Var_) =                           \
        make_log_var(__func__, __FILE__, __LINE__, #Var_, Var_);
最后,最后一个缺失部分(好吧,我想除了您想要的实际上下文之外):一个基本异常类的示例

class ContextualException: public virtual std::exception {
public:
    ContextualException(): _c(ContextInterface::SetActive<ExceptionContext>()) {}

    ContextInterface const& context() const { return *_c; }

private:
    ContextInterface::SPtr _c;
}; // class ContextualException
类上下文异常:公共虚拟std::异常{ 公众: ContextalException():c(ContextInterface::SetActive()){} ContextInterface常量&context()常量{return*_c;} 私人: ContextInterface::SPtr\u c; };//类上下文异常
这些文本描述应该固有地链接到异常类,而不是作为运行时数据写入每个实例


类似地,所有这些信息性数据都应该是exception类的成员,您可以在以后将其格式化为文本输出(可能在exception类本身的成员函数中).

您可以使用Boost Exception简化向异常对象添加任意数据的过程,并在它们在调用堆栈中冒泡时使用更多相关数据来扩充它们。您不必担心预先定义可能需要存储在异常中的所有内容,因为您可以根据需要存储任何异常的数据。

首先,const用构造函数而不是一堆设置器来构造对象。这就是构造函数的作用。其次,你的异常是一堆字符串,只要将它们格式化为一个大的、用户可呈现的字符串并激发就行了。你是否尝试过编写一个生成异常的函数(即,除了抛出的
行之外,包含所有内容),只需执行
抛出exceptionGenerator()
或者您如何调用该函数?该函数如何访问我程序中的变量列表?这意味着我必须通过参数传递它们,然后我们回到原点。是否有方法自动将所有变量添加到我的异常类中?该函数如何访问我程序中的变量列表y程序?这意味着我必须通过参数传递它们,我们回到了第一步。有没有办法让所有变量自动添加到我的异常类?谢谢你的想法。但我仍然在寻找一种更干净的方法,可以自动添加所有变量,我所要做的就是编写错误消息,然后如果您知道我的意思,希望程序自动处理程序中多个点的相同变量名和当前值。@SamerAfach我认为我更新的答案非常接近您的要求。请稍作修改,并让我知道这是否有帮助。:)对该方法的评论?@MatthieuM。谢谢您的回复。为什么我它不是线程安全的吗?只有在创建变量或引发异常时才需要访问向量_allParams,并且您可以使用映射来访问它
class ContextualException: public virtual std::exception {
public:
    ContextualException(): _c(ContextInterface::SetActive<ExceptionContext>()) {}

    ContextInterface const& context() const { return *_c; }

private:
    ContextInterface::SPtr _c;
}; // class ContextualException