在C++中引发基元类型

Throwing primitive types in C++

本文关键字:类型 C++      更新时间:2023-10-16

我正在处理一个对话框,该对话框向用户请求文件、用户名和密码。我希望用户在选择出现问题时得到通知。在检查对话框的名称和密码字段之前,文件必须是有效的。我知道还有其他方法可以做到这一点,我的问题是这个过程的效率。

我的MFC C++应用程序有一个字符串表,其中使用将转换单元映射到整数(#define IDS_SOME_ERROR 100)的宏来标识字符串,其中MFC框架可以使用这些整数从字符串表加载字符串。

我对抛出基元类型的效率很好奇,所以我研究了cpprrefence.com.上的throw关键字

throw expression语句副本从表达式初始化异常对象(这可能会调用右值表达式的move构造函数,并且副本/移动可能会受到副本省略),然后将控制权转移到具有匹配类型的异常处理程序,该异常处理程序的复合语句或成员初始值设定项列表最近被此执行线程输入而未退出。即使复制初始化选择了移动构造函数,从左值进行的复制初始化也必须格式正确,并且析构函数必须是可访问的(因为C++14)。

这是另一个关于抛出类型的问题,我注意到一条评论说不要抛出intstring之类的东西。为什么会这样?

这是我的代码:

void SomeDialog::OnOK()
{   
UpdateData();
try
{
if (VerifySomeFile(myFileStruct.getPath()))
{
if (DialogNameField.IsEmpty())
{
throw IDS_ERROR_NOID; // "No name specified."
}
if (DialogPasswordField.IsEmpty())
{
throw IDS_ERROR_NOPWD; // "No password specified."
}
CDialog::OnOK();
}
else
{
throw IDS_BAD_FILE; // "Bad or expired file."
}
}
catch (int errIDS)
{ 
CString tempStr;
tempStr.LoadString(errIDS);
AfxMessageBox(tempStr, MB_OK);
}
}

既然int是C++中的基元类型,那么throw语句还需要执行任何复制吗?以这种方式在C++中抛出基元类型安全吗?移除catch块并将我的错误对话框逻辑从catch块放置到每个抛出位置会更有效吗?如果我要这样做,我还必须嵌套我的代码,以便在出现多个错误时只显示一个对话框。

您不应该过于担心的效率,因为捕获std::exeption衍生物的推荐做法是无论如何使用const引用。

它的优点是引入了异常层次结构,并使用const char* std::exception::what() const提供重写的错误消息。

我认为这样做会更好,而不是抛出内置类型:

struct SomeError{int errid};
...
throw SomeError{IDS_BAD_FILE};

让我们从正确使用术语开始。C++没有基元类型的概念。在C++中,有内置类型和自定义类型。

就这点而言,int是一个内置类型。虽然从语言的角度来看,抛出int类型的对象与抛出MySpecialClass类型的对象或std::exception的派生对象没有什么不同,但抛出后者有一个好处——因为这是一个众所周知的例外,人们可能会认为程序中的某个位置会有catch (const std::exception& e)。这个catch将处理std::exception的所有派生,并且至少可以在异常中打印消息。

然而,期望一个人赶上int是不合理的!即使这样,下一步会怎样?应该如何处理此异常?打印到控制台的数字?用户应该如何看待它?