什么是在C ++中返回错误代码的正确方法

时间:2022-06-20 02:04:44

I'm using error codes for handling errors in my c++ project. The problem is how to return error codes from a function which is supposed to return some variable/object.

我正在使用错误代码来处理我的c ++项目中的错误。问题是如何从一个应该返回某个变量/对象的函数返回错误代码。

consider this:

long val = myobject.doSomething();

Here, myobject is an object of some class. If doSomething function encounters some error condition then how should it notify the caller (Without using exceptions).

在这里,myobject是某个类的对象。如果doSomething函数遇到某些错误条件,那么它应该如何通知调用者(不使用异常)。

Possible solutions:

  1. Have a data member (say err_) in the class which can be checked by the caller. But it would be unsafe in a multi-threaded application sharing the same object and calling the same function.
  2. 在类中有一个数据成员(比如err_),可以由调用者检查。但是,在共享同一个对象并调用相同函数的多线程应用程序中,这将是不安全的。

  3. Use some global error variable, again same issue in a multi-threaded environment.
  4. 使用一些全局错误变量,在多线程环境中也是同样的问题。

Now how can I notify the caller about some error condition?

现在如何通知调用者一些错误情况?

11 个解决方案

#1


5  

You can pass variable as reference and return error code in it.

您可以将变量作为引用传递并在其中返回错误代码。

#2


28  

Make a template called, say, Maybe that it parametrized by your return value type. Whenever you return a value, wrap it in this template like this:

制作一个名为的模板,比方说,也许它是按你的返回值类型进行参数化的。每当您返回一个值时,将其包装在此模板中,如下所示:

Maybe<long> result = object.somemethod();

The Maybe template would have a way of being instantiated with an error code (probably a static method):

Maybe模板可以通过错误代码(可能是静态方法)进行实例化:

return Maybe<long>::error(code);

But ordinarily would just be returned with the value:

但通常会返回值:

Maybe<long> retval;
retval = 15;
return retval;

(You would have to, of course, override the appropriate constructors, assignment operators, etc.)

(当然,您必须覆盖适当的构造函数,赋值运算符等)

In the client side you call a method to check for the error.

在客户端,您调用一个方法来检查错误。

Maybe<long> result = object.somemethod();
if (result.is_error) 
{ 
    ... handle the error ...
}
else
{
    ... use the result ...
}

Again you'd need the appropriate operators defined to use Maybe<long> wherever there's a long required.

同样,您需要使用定义的相应运算符,以便在需要很长时间的地方使用Maybe

This sounds like a lot of work, but really the work is done once in making a good, bulletproof Maybe template. You'll also have to do some performance tuning on it to avoid nasty overheads. If you want to make it more flexible you can parametrize it on both the return value type and the error type. (This is only a minor increase in complexity.)

这听起来像是很多工作,但实际上这项工作只需要制作一个好的,防弹的Maybe模板。您还必须对其进行一些性能调整,以避免令人讨厌的开销。如果要使其更加灵活,可以在返回值类型和错误类型上对其进行参数化。 (这只是复杂性的微小增加。)

#3


7  

You probably want something like Alexandresu's Expected<T> idiom.

你可能想要像Alexandresu的预期 成语。

#4


3  

It is common to return a return/error code, and make available a property or member with the results.

通常返回返回/错误代码,并使结果具有属性或成员。

int retCode = myobject.doSomething();
if (retCode < 0){ //Or whatever you error convention is
   //Do error handling
}else{
   long val = myobject.result;
}

It is also common to pass in a pointer that is set to the return value, and return the return/error code. (See HrQueryAllRows).

传入一个设置为返回值的指针也很常见,并返回返回/错误代码。 (参见HrQueryAllRows)。

long val = INIT_VAL;
int retCode = myObject.doSomething(&val);

if (retCode < 0){
    //Do error handling
}else{
    //Do something with val...
}

#5


2  

Return an error handle. Have an error manager keep the error codes and additional informations (e.g. ERROR_INVALID_PARAMETER and name-value-pairs like ParameterName="pszFileName"). This information can be accessed using the handle. The caller can check the error handle against a NO_ERROR_HANDLE. If true, no error occurred. The caller can augment the error information and pass the handle up the stack. The error manager can be one for the process or one for each thread.

返回错误句柄。让错误管理器保留错误代码和其他信息(例如ERROR_INVALID_PARAMETER和名称 - 值对,如ParameterName =“pszFileName”)。可以使用句柄访问此信息。调用者可以针对NO_ERROR_HANDLE检查错误句柄。如果为true,则不会发生错误。调用者可以扩充错误信息并将句柄传递给堆栈。错误管理器可以是进程的一个,也可以是每个线程的一个。

#6


2  

You have three options:

你有三个选择:

Create a class containing the return value and a possible error code.

创建一个包含返回值和可能的错误代码的类。

Use something like boost::optional for the return value, which allows for invalid responses.

对返回值使用boost :: optional之类的东西,这允许无效的响应。

Pass a reference to a variable and return any possible error code within that.

传递对变量的引用并返回其中的任何可能的错误代码。

#7


2  

You can use exceptions.

您可以使用例外。

#8


2  

I would suggest following:

我建议遵循:

class foo {
public:
    long doSomething();
    long doSomething(error_code &e);
};

Where error_code is some type that holds error. It may be integer or better something based on boost::system::error_code.

其中error_code是某种保存错误的类型。它可能是基于boost :: system :: error_code的整数或更好的东西。

And you supply two functions:

你提供两个功能:

  1. First version throws the error, for example throw boost::system::system_error that is created from boost::system::error_code.
  2. 第一个版本抛出错误,例如抛出boost :: system :: error_code创建的boost :: system :: system_error。

  3. Second returns the error code into e.
  4. 第二个将错误代码返回到e。

#9


2  

The most common practice is to return the error code

最常见的做法是返回错误代码

long result;
int error = some_obj.SomeMethod(&result);

or return a value that indicate there was an error:

或返回一个表明存在错误的值:

long result = some_obj.SomeMethod();
if (result < 0) error = some_obj.GetError();

#10


0  

define all the error codes in a File. based on error category you can return the error code and the caller can decide what went wrong and caller can return its own error code.

定义文件中的所有错误代码。根据错误类别,您可以返回错误代码,调用者可以决定出错的地方,调用者可以返回自己的错误代码。

for example

#define FILE_ERROR        1
#define SANITY_ERROR      2

int WriteToFile(char* Data, int iErrorCode)
{
   char* FileName;

  if (!FileOpen(FileName, &iErrorCode))
  {
     //Analyze error code and make decision on what to ignore or terminate
     iErrorCode = FILE_ERROR;
     return 0;
  }

}

int FileOpen(char* FileName, int* iErrorCode)
{

    if (FileName == null)
     {
       iErrorCode = SANITY_ERROR;
      return 0;
    }

    ///// next code blocks
    return 1;
}

#11


0  

You can return a std::pair holding both an error code (or error object) and the desired return object. The object of interest needs a default constructor or value so you can return something even when an error is encountered.

您可以返回一个std :: pair,同时包含错误代码(或错误对象)和所需的返回对象。感兴趣的对象需要一个默认的构造函数或值,因此即使遇到错误也可以返回一些内容。

#1


5  

You can pass variable as reference and return error code in it.

您可以将变量作为引用传递并在其中返回错误代码。

#2


28  

Make a template called, say, Maybe that it parametrized by your return value type. Whenever you return a value, wrap it in this template like this:

制作一个名为的模板,比方说,也许它是按你的返回值类型进行参数化的。每当您返回一个值时,将其包装在此模板中,如下所示:

Maybe<long> result = object.somemethod();

The Maybe template would have a way of being instantiated with an error code (probably a static method):

Maybe模板可以通过错误代码(可能是静态方法)进行实例化:

return Maybe<long>::error(code);

But ordinarily would just be returned with the value:

但通常会返回值:

Maybe<long> retval;
retval = 15;
return retval;

(You would have to, of course, override the appropriate constructors, assignment operators, etc.)

(当然,您必须覆盖适当的构造函数,赋值运算符等)

In the client side you call a method to check for the error.

在客户端,您调用一个方法来检查错误。

Maybe<long> result = object.somemethod();
if (result.is_error) 
{ 
    ... handle the error ...
}
else
{
    ... use the result ...
}

Again you'd need the appropriate operators defined to use Maybe<long> wherever there's a long required.

同样,您需要使用定义的相应运算符,以便在需要很长时间的地方使用Maybe

This sounds like a lot of work, but really the work is done once in making a good, bulletproof Maybe template. You'll also have to do some performance tuning on it to avoid nasty overheads. If you want to make it more flexible you can parametrize it on both the return value type and the error type. (This is only a minor increase in complexity.)

这听起来像是很多工作,但实际上这项工作只需要制作一个好的,防弹的Maybe模板。您还必须对其进行一些性能调整,以避免令人讨厌的开销。如果要使其更加灵活,可以在返回值类型和错误类型上对其进行参数化。 (这只是复杂性的微小增加。)

#3


7  

You probably want something like Alexandresu's Expected<T> idiom.

你可能想要像Alexandresu的预期 成语。

#4


3  

It is common to return a return/error code, and make available a property or member with the results.

通常返回返回/错误代码,并使结果具有属性或成员。

int retCode = myobject.doSomething();
if (retCode < 0){ //Or whatever you error convention is
   //Do error handling
}else{
   long val = myobject.result;
}

It is also common to pass in a pointer that is set to the return value, and return the return/error code. (See HrQueryAllRows).

传入一个设置为返回值的指针也很常见,并返回返回/错误代码。 (参见HrQueryAllRows)。

long val = INIT_VAL;
int retCode = myObject.doSomething(&val);

if (retCode < 0){
    //Do error handling
}else{
    //Do something with val...
}

#5


2  

Return an error handle. Have an error manager keep the error codes and additional informations (e.g. ERROR_INVALID_PARAMETER and name-value-pairs like ParameterName="pszFileName"). This information can be accessed using the handle. The caller can check the error handle against a NO_ERROR_HANDLE. If true, no error occurred. The caller can augment the error information and pass the handle up the stack. The error manager can be one for the process or one for each thread.

返回错误句柄。让错误管理器保留错误代码和其他信息(例如ERROR_INVALID_PARAMETER和名称 - 值对,如ParameterName =“pszFileName”)。可以使用句柄访问此信息。调用者可以针对NO_ERROR_HANDLE检查错误句柄。如果为true,则不会发生错误。调用者可以扩充错误信息并将句柄传递给堆栈。错误管理器可以是进程的一个,也可以是每个线程的一个。

#6


2  

You have three options:

你有三个选择:

Create a class containing the return value and a possible error code.

创建一个包含返回值和可能的错误代码的类。

Use something like boost::optional for the return value, which allows for invalid responses.

对返回值使用boost :: optional之类的东西,这允许无效的响应。

Pass a reference to a variable and return any possible error code within that.

传递对变量的引用并返回其中的任何可能的错误代码。

#7


2  

You can use exceptions.

您可以使用例外。

#8


2  

I would suggest following:

我建议遵循:

class foo {
public:
    long doSomething();
    long doSomething(error_code &e);
};

Where error_code is some type that holds error. It may be integer or better something based on boost::system::error_code.

其中error_code是某种保存错误的类型。它可能是基于boost :: system :: error_code的整数或更好的东西。

And you supply two functions:

你提供两个功能:

  1. First version throws the error, for example throw boost::system::system_error that is created from boost::system::error_code.
  2. 第一个版本抛出错误,例如抛出boost :: system :: error_code创建的boost :: system :: system_error。

  3. Second returns the error code into e.
  4. 第二个将错误代码返回到e。

#9


2  

The most common practice is to return the error code

最常见的做法是返回错误代码

long result;
int error = some_obj.SomeMethod(&result);

or return a value that indicate there was an error:

或返回一个表明存在错误的值:

long result = some_obj.SomeMethod();
if (result < 0) error = some_obj.GetError();

#10


0  

define all the error codes in a File. based on error category you can return the error code and the caller can decide what went wrong and caller can return its own error code.

定义文件中的所有错误代码。根据错误类别,您可以返回错误代码,调用者可以决定出错的地方,调用者可以返回自己的错误代码。

for example

#define FILE_ERROR        1
#define SANITY_ERROR      2

int WriteToFile(char* Data, int iErrorCode)
{
   char* FileName;

  if (!FileOpen(FileName, &iErrorCode))
  {
     //Analyze error code and make decision on what to ignore or terminate
     iErrorCode = FILE_ERROR;
     return 0;
  }

}

int FileOpen(char* FileName, int* iErrorCode)
{

    if (FileName == null)
     {
       iErrorCode = SANITY_ERROR;
      return 0;
    }

    ///// next code blocks
    return 1;
}

#11


0  

You can return a std::pair holding both an error code (or error object) and the desired return object. The object of interest needs a default constructor or value so you can return something even when an error is encountered.

您可以返回一个std :: pair,同时包含错误代码(或错误对象)和所需的返回对象。感兴趣的对象需要一个默认的构造函数或值,因此即使遇到错误也可以返回一些内容。