处理错误的参数值

时间:2016-04-05 12:41:57

标签: c++ error-handling

我有以下功能(C ++):

string dataInYear(int year) {
  if (year < 2000) {
     //don't support retrieving data from before 2000
  }
  //return data for the year >= 2000
}

如果年份&lt; 2000?如何将输出错误字符串用作参数:

string dataInYear(int year, string &error) {
  if (year < 2000) {
     error = "don't support retrieving data from before 2000";
     return "";
  }
  //return data for the year >= 2000
}

我不确定使用异常的原因是调用者不会仅仅通过查看头文件知道该函数可以抛出异常(而不仅仅是返回一个空字符串)。使用第二个选项,调用者必须通过传入错误字符串并在之后检查它来确认方法可能失败。

或作为第三种选择:

template <class A> struct Failable
{
  bool error;
  A value;
  wxString errorString;
  Failable(wxString errorStr) :  error(true), errorString(errorStr) {}
  Failable(A val) : error(false), value(val) {}
  operator A() const { return value; }
};

Failable<string> dataInYear(int year) {
      if (year < 2000) {
         error = "don't support retrieving data from before 2000";
         return "";
      }
      //return data for the year >= 2000
}

//caller

Failable<string> d = dataInYear(y);
if (d.error) {
  //deal with error
} else {
  string data = d.value;
}

3 个答案:

答案 0 :(得分:1)

  

我不确定使用异常的原因是调用者不知道只是通过查看头文件,此函数可以抛出异常 < / p>

嗯,可能,使用throw关键字:

// Header.h
string dataInYear(int year) throw(std::exception);

但是,如果你觉得exception specifications are bad,那么你可以只评论那部分。至少告诉用户这个功能'可以'throw 或者,如您已在帖子中指出的那样,返回一个空字符串。

auto result = dataInYear(year);
if(result.empty())
  // ... error

假设你不喜欢它们,那么它有一个简单的结构,其中包含错误代码。

template<typename Data>
struct Result
{
  Data data;  // any type can be used besides string
  string error;
};

Result<string> dataInYear(int year)
{
  if(year < 2000)
    return Result<string>{"", "don't support retrieving data from before 2000"};

  return Result<string>{data};
}

...

auto result = dataInYear(year);
if(not result.error.empty())  // if `error` is filled => problem
  // ... error

答案 1 :(得分:0)

使用异常规范的替代方法可能是这样的:

#include <string>

class APIExample 
{
   std::string m_sErrorMessage;

public:
   APIExample() : m_sErrorMessage("")
   {}

   enum class ReturnCode {
      Ok,
      Error, // Possible to add more codes if you'd like
   };

   ReturnCode dataInYear(int nYear, std::string & sData)
   {
      if (nYear < 2000) {
         m_sErrorMessage = "Year is < 2000";
         return ReturnCode::Error;
      }
      return ReturnCode::Ok;
   }

   ReturnCode getErrorMessage(std::string & sErrorMessage)
   {
      sErrorMessage = m_sErrorMessage;

      return ReturnCode::Ok;
   }
};

int main()
{

   APIExample example;
   std::string sData;
   if (example.dataInYear(1000, sData) != APIExample::ReturnCode::Ok) {
      std::string sError;
      example.getErrorMessage(sError);
   }
    return 0;
}

请注意enum class ReturnCode可以使用其他错误/警告代码进行扩展。

答案 2 :(得分:0)

  

我不确定使用异常的原因是调用者不会仅仅通过查看头文件知道该函数可以抛出异常(而不仅仅是返回一个空字符串)。

他们应该!你的文件评论在哪里?这些应该声明在违反前提条件时可能会抛出异常。而且,无论你是否使用例外,前提条件本身都应该列在所述文档评论中,所以这个问题变得毫无意义:错误参数不比异常更好或更差,方面

与此同时,异常的所有其他好处都会产生(我在此不再赘述)。