我刚才读到,在C++ 11标准版本中,异常规范已被弃用.我以前认为指定你的功能可能是好的做法,但显然,不是这样.
在阅读了Herb Stutter引用得很好的文章之后,我不禁要问:为什么实际上是按照它们的方式实现了异常规范,为什么委员会决定弃用它们而不是在编译时检查它们?为什么编译器甚至允许抛出一个未出现在函数定义中的异常?对我来说,这听起来像是在说"你可能不应该指定你的函数返回类型,因为当你指定时int f(),但return 3.5;在它内部,你的程序可能会崩溃." (即强类型的概念差异在哪里?)
(由于typedefs中缺少异常规范支持,假设模板语法可能是Turing-complete,实现这个听起来很容易.)
我最近得到了一个已被其他人实现的dll.我必须在我的应用程序中使用它.在他们类的头文件中,他们有函数声明
void func1() throw (CCustomException);
Run Code Online (Sandbox Code Playgroud)
现在,当我编译它时,我收到警告,
忽略C++异常规范,除非指示函数不是_declspec(nothrow)
我阅读了MSDN - 文档,但无法理解它.另外,我不想因为它出现而禁用警告.我想知道我做错了什么而不是禁用它.
我认为我的功能,比如 从dll myfunc()访问func1()它没有那个Exception规范列表.因此,我尝试在我的函数中使用相应的异常规范列表,
void myfunc1() throw (CCustomException);
Run Code Online (Sandbox Code Playgroud)
但我仍然收到警告.什么是警告以及如何摆脱它?我在Windows XP中使用Qt 4.5.
请考虑以下代码:
class A
{
public:
virtual void f() throw ( int ) { }
};
class B: public A
{
public:
void f() throw ( int, double ) { }
};
Run Code Online (Sandbox Code Playgroud)
在编译时,它表示派生类B与A相比具有更宽松的抛出说明符.这有什么重要性?如果我们尝试交换它们的异常规范,例如A :: f()抛出int和double而B :: f()只抛出int,则不会出现错误.
C++ 14标准定义了find()成员函数,std::map如下所示:
iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
Run Code Online (Sandbox Code Playgroud)
为什么这些功能没有定义为noexcept?内部可能出错的地方,需要抛出一个异常或产生未定义的行为(除了没有找到一个元素,在这种情况下函数返回一个end迭代器并且无论如何都不需要抛出异常)?
我有两个关于非投掷功能的问题:
为什么要使一个函数不抛?
如何使功能不抛?如果函数内部的代码实际可能throw,那么我还应该让它不抛?
这是一个例子:
void swap(Type t1, Type t2) throw()
{
//swap
}
Run Code Online (Sandbox Code Playgroud)
如果代码中swap根本不会抛出,我还应该追加throw()吗?为什么?
在C++ 14 Sec 15.4; 2中声明,......异常规范不应出现在typedef声明或别名声明中.
这意味着禁止以下内容:
typedef void (*fn)(int) noexcept;
Run Code Online (Sandbox Code Playgroud)
但是,措辞不会出现意味着令牌noexcept不能出现在typedef声明中的任何地方吗?
比如这些都是禁止的吗?
typedef void (*fn1)(void (*)(int) noexcept);
typedef decltype(std::declval<void (*)(int)noexcept>()) fn2;
Run Code Online (Sandbox Code Playgroud)
这两个都试图定义一个类型fn1,fn2并且能够指向一个函数,该函数接受一个函数的指针,该函数接受int并且不返回任何内容,同时承诺永远不会抛出异常.
因此在我的示例中,异常规范不适用于顶层类型fn1resp.fn2由typedef这些函数可能接收的参数引入.
那么我应该逐字取15.4; 2,因此我的两个例子都无效?或者只是应用于禁止的类型定义,我的例子是正确的?
尝试/捕获异常或使用if语句来处理不同的结果是否更好?
我正在用Java编写一个简短的程序来复制文件以方便使用,并使用ifs来处理文件不存在的事件,并为每个方法声明抛出,但不要使用try/catch.
我应该回去用try/catches替换那些ifs和相关部分,还是这个"可接受的"编程"用于与小型用户社区共享?
第一个免责声明:这不是导致"语言战争".对于我的报告,我真的需要这个(关于这个主题的澄清),我只想拥有有效而坚实的论据.
好的,所以这里有一个问题:
在C++中,异常规范已从C++ 11标准中删除,因为它被认为造成了更多的伤害而不是好处.
另一方面,在Java中,异常规范被视为好的和有用的东西.
在这两种语言中,这两个概念(具有异常规范的目的)是不同的,这就是为什么它们被这两个社区看得不同或者那些概念是相似/相同的?
哪一个?异常规范是好事还是坏事?或者它在Java中很好,因为(在这里我想看到一些原因)并且在C++中很糟糕,因为(原因在这里).
感谢任何有建设性帮助的人.
最近,一位同事询问了我对C++代码中异常规范的使用的看法,并且我能够通过Herb Sutter挖掘这篇文章:一个实用的异常规范.像Herb Sutter一样,这篇文章是一本教育读物,但简短的回答是"不要这样做".
在摘要中,他提到了一首题为"实施之前的夜晚"的诗,其中,有效地,标准委员会鞠躬要求用户在最后一分钟添加一个功能,只是发现虽然它做了什么是要求,它并没有真正做他们想要的.是的,异常规范符合该法案.正如他所说,"这个功能在当时似乎是个好主意,而且正是有些人要求的." 如果这还不够,那么他会以类似的悲伤结果访问"出口".
所以问题是:如果你不想体验眼泪,那么C++的"特征"会被打破,不应该被使用.这可能是主观争吵的牺牲品,但我希望人们会引用一个特定的体验,其中部署该功能只会导致可测量的问题.更好的方法是引用像Sutter(或任何深入参与标准的人)这样的引人注目的文章,警告人们不要使用某个功能.
我已经阅读了很多关于(不)使用throw(X)函数签名的论点,我认为它在ISO C++中指定的方式(并在当前编译器中实现)它相当无用.但是为什么编译器不能简单地在编译时强制执行异常正确性呢?
如果我编写包含throw(A,B,C)在其签名中的函数/方法定义,编译器在确定给定函数的实现是否异常正确时应该没有太多问题.这意味着功能体具有
throw的其他比throw A; throw B; throw C;;throw (A,B,C);,至少在外面try{}catch()捕捉其他抛出的类型.如果编译器在不满足这些要求时引发错误,那么所有函数都应该是"安全的",并且不需要运行时函数unexpected().所有这些都将在编译时得到保证.
void fooA() throw (A){
}
void fooAB() throw (A,B){
}
void fooABC() throw (A,B,C){
}
void bar() throw (A){
throw A(); // ok
throw B(); // Compiler error
fooA(); // ok
fooAB(); // compiler error
fooABC(); // compiler error
try{
throw A(); // ok
throw B(); // ok
throw C(); // Compiler …Run Code Online (Sandbox Code Playgroud)