我想创建一个类和枚举来处理项目中的错误。到目前为止,我正在按照以下方式进行操作。
enum class eErrorType
{
eJsonFileNotFound = 0,
eJsonInvalidFormat,
eJsonKeyNotFound,
eJsonEmptyArray,
eNoError,
eCustom
};
class Error
{
public:
// Constructors
Error() { errorType = eErrorType::eNoError; message = ""; }
Error(eErrorType type) { errorType = type; SetMessage(type); }
Error(std::string msg) { errorType = eErrorType::eCustom; message = msg; }
// Public Methods
std::string getErrMessage() { return message; }
private:
eErrorType errorType;
std::string message;
void SetMessage(eErrorType type)
{
switch (type)
{
case eErrorType::eJsonFileNotFound: message = "Json file not found"; break;
case eErrorType::eJsonInvalidFormat: message = "Invalid json file"; break;
case eErrorType::eJsonKeyNotFound: message = "Specified key is not found in json"; break;
case eErrorType::eJsonEmptyArray: message = "No elements in json array"; break;
case eErrorType::eNoError: message = "Entry contained an attempt to divide by zero!"; break;
default: message = ""; break;
}
}
};
int main()
{
try
{
//open json file. If file open failed, throw error
throw eErrorType::eJsonFileNotFound;
//parse json file. If parsing failed, throw error
throw eErrorType::eJsonInvalidFormat;
//check for particular key in the json. If not found, throw error
throw eErrorType::eJsonKeyNotFound;
}
catch (eErrorType errCode)
{
Error errObj(errCode);
std::cout << errObj.getErrMessage() << std::endl;
}
return 0;
}
我想提出一些改进建议。有没有更好的方法或基于语言的功能可以实现此目的。
答案 0 :(得分:3)
对于自定义错误,您可以从std :: exception继承,重写异常方法并实现自己的东西,例如:
#include <exception> // std::exception
//
// custom exception class
//
class error final :
public std::exception
{
public:
error(const char* description, short code = -1) throw() :
description(description), code(code) { }
const char* what() const throw() override
{
return description;
}
short Code() const throw()
{
return code;
}
error(error&& ref)
: description(ref.description), code(ref.code) { }
error& operator=(error&&)
{
return *this;
}
error(const error& ref)
: description(ref.description), code(ref.code) { }
private:
const char* description;
const short code;
error& operator=(const error&) = delete;
};
定义一个宏以显示发生错误的文件名:
#include <cstring> // std::strrchr
// Show only file name instead of full path
#define __FILENAME__ (std::strrchr(__FILE__, '\\') ? std::strrchr(__FILE__, '\\') + 1 : __FILE__)
定义通用功能以显示错误(以下实现会显示消息框,但您可以将其重新定义为控制台程序)
#include <string>
#include <windows.h>
#include <codecvt> // string conversion std::wstring_convert and std::codecvt_utf8
//
// converts string or const char* to wstring
//
std::wstring stringToWstring(const std::string& t_str)
{
//setup converter
typedef std::codecvt_utf8<wchar_t> convert_type;
std::wstring_convert<convert_type, wchar_t> converter;
//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
return converter.from_bytes(t_str);
}
//
// Set error message to your liking using error class
// and show message box, this function is also used to pass in
// std::exception objects
//
template <typename ExceptionClass>
void ShowError(
HWND hWnd,
ExceptionClass exception,
const char* file,
int line,
long info = MB_ICONERROR)
{
std::string error_type = TEXT("Rutime Error");
std::string error_message = TEXT("File:\t");
#ifdef UNICODE
error_message.append(stringToWstring(file));
#else
error_message.append(file);
#endif // UNICODE
error_message.append(TEXT("\r\nLine:\t"));
error_message.append(std::to_string(line));
error_message.append(TEXT("\r\nError:\t"));
#ifdef UNICODE
error_message.append(stringToWstring(exception.what()));
#else
error_message.append(exception.what());
#endif // UNICODE
// Show error message
MessageBox(hWnd,
error_message.c_str(),
error_type.c_str(), static_cast<UINT>(MB_OK | info));
}
然后显示如下错误:
ShowError(nullptr, error("You error message"), __FILENAME__, __LINE__);
对于Win32 / COM错误类型,该函数可以像这样重载:
#include <comdef.h> // _com_error
#include <windows.h>
#include <string>
//
// Format error code into a string and show message box
// COM and System errors
//
void ShowError(HWND hWnd, const char* file, int line, HRESULT hr = S_OK)
{
string error_type = TEXT("Rutime Error");
string error_message = TEXT("File:\t");
#ifdef UNICODE
error_message.append(stringToWstring(file));
#else
error_message.append(file);
#endif // UNICODE
error_message.append(TEXT("\r\nLine:\t"));
error_message.append(std::to_string(line));
error_message.append(TEXT("\r\nError:\t"));
// If HRESULT is omited or S_OK
// format last error code message
if (hr == S_OK)
{
LPVOID lpBuff = nullptr;
DWORD dwChars = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
nullptr,
GetLastError(),
0,
reinterpret_cast<LPTSTR>(&lpBuff),
0,
nullptr);
// If the function succeeds, the return value is
// the number of TCHARs stored in the output buffer
if (dwChars)
{
error_message.append(reinterpret_cast<LPCTSTR>(lpBuff));
}
else // If the function fails, the return value is zero
{
error_message.append(TEXT("Unknown Error\t"));
error_message.append(to_string(GetLastError()));
}
// Free the buffer allocated by FormatMessage
LocalFree(lpBuff);
}
else // Format com error code into a message
{
_com_error err(hr);
error_message.append(err.ErrorMessage());
}
// Play the sound and show error message
MessageBox(hWnd,
error_message.c_str(),
error_type.c_str(), MB_OK | MB_ICONERROR);
}
对于系统错误,该函数的调用略有不同:
ShowError(nullptr, __FILENAME__, __LINE__); // type hresult if needed
修改:
我从项目中复制了代码,目前std::to_string
提到的仅适用于ANSI版本,您需要修改ShowError
函数以有条件地将std::to_wstring
用于unicode。
同样,ShowError函数中的string
也是ANSI字符串,如果您不愿意,可以有条件地使用wstring
或为字符串定义宏:
#ifdef UNICODE
typedef std::wstring string;
#else
typedef std::string string;
#endif // UNICODE
如果需要,也可以to_string
使用
// conditionaly use string or wide string
#ifdef UNICODE
#define to_string std::to_wstring
#else
#define to_string std::to_string
#endif // UNICODE
如果您希望避免在每个单独的函数调用中都键入错误消息,则还可以实现enum class
代码类型,并将它们作为第二个或第三个附加参数传递给异常类,并实现显示自定义错误代码。
还请注意,ShowError
函数可用于catch语句内的std错误,您只需在其中传递std错误对象,例如:
try
{
// example, or do some heavy memory allocation here to throw
throw std::bad_alloc;
}
catch(std::bad_alloc& err);
{
ShowError(nullptr, err, __FILENAME__, __LINE__);
}
可以扩展此方法,以修改功能以同时格式化NTSTATUS消息
有关Win32中可能的错误消息的完整列表,请参见this。
有关上述代码中使用的功能的其他信息,请参见以下链接:
一些代码已从此站点复制,例如: