这是我的一个面试问题。处理构造函数的异常
令人惊讶的是,我从来没有想过给自己一个这样的问题。
我们可以在构造函数C++中有异常处理吗?
现在时态并没有多想我说“是的,我们可以做一个constructor.lets说我们正在使用new运算符分配一些内存到一个指针成员,它会抛出一个错误的alloc异常,这样就有可能会有异常提出“
然后后来我认为构造函数永远不会返回一个值。那么构造函数中的异常怎么会被抓到。现在我问这个问题了!
有人能帮我摆脱这种困惑吗?
这是我的一个面试问题。处理构造函数的异常
令人惊讶的是,我从来没有想过给自己一个这样的问题。
我们可以在构造函数C++中有异常处理吗?
现在时态并没有多想我说“是的,我们可以做一个constructor.lets说我们正在使用new运算符分配一些内存到一个指针成员,它会抛出一个错误的alloc异常,这样就有可能会有异常提出“
然后后来我认为构造函数永远不会返回一个值。那么构造函数中的异常怎么会被抓到。现在我问这个问题了!
有人能帮我摆脱这种困惑吗?
看到这个GOTW Constructor Failures问题哪些地址您的查询有点并继续说这是浪费时间。
+1我打算写一个关于function-try-block的选项和它的许多缺陷,但我不会接近Sutter的描述:) – 2011-04-21 10:57:17
这是一篇非常有趣的文章,def + 1 – Justin 2011-04-21 19:15:04
C++具有类似于其他语言的try-catch子句。该教程可以在网上查到:http://www.cplusplus.com/doc/tutorial/exceptions/
编辑:例如变成完全的工作代码
#include <iostream>
using namespace std;
class A
{
public:
void f(){
throw 10;
}
A(){
try{
f();
}
catch(int e){
cout << "Exception caught\n";
}
}
};
int main (int argc, const char * argv[])
{
A a;
return 0;
}
这将产生输出:
Exception caught
@ laas.i知道有很多documents.But我特别要求在构造函数中的异常处理。这并不代表我的问题。 – Vijay 2011-04-21 10:50:09
C++没有'finally'块,并且C++中的异常处理在许多方面与Java等语言有所不同,例如对于清理,C++使用http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization – helpermethod 2011-04-21 10:53:14
@Helper方法 - 你当然是对'finally'正确的,但据我了解,@ zombie询问**构造函数内的异常处理**,所以我的示例仍然有效,或者应该纠正问题。我用更多的代码更新我的答案。 – Laas 2011-04-21 11:27:45
构造函数没有返回类型, 所以不可能使用返回码 。 构造函数失败的最好方法是因此给 抛出异常。如果你没有 使用异常的选项, “最不坏”的解决办法是把 对象变成“僵尸”状态由 设置内部状态位使 对象的行为有点像它的尽管它在技术上仍然 活着,但它仍然死亡。
你会赶上调用代码例外,而不是在构造函数中。
查看How can I handle a constructor that fails?了解更多详情(实际上,我建议阅读关于异常处理的整个页面,真正有启发性)。
我读过这篇文章,但我期待人们在这种场景中使用的一些实用方法。 – Vijay 2011-04-21 10:51:31
+1,但人们必须说这个问题也有点棘手。通常,当你以某种方式在构造函数中失败时,它就会抛出一个构造函数,这完全可以在构造函数中尝试/捕获以处理其他失败并避免构造函数首先失败(或重新抛出)。根据情况,这可能是可取的。例如,如果在构造函数中构造两个对象,并且第二个引发bad_alloc,那么你会怎么做?捕获调用代码中的异常将泄漏第一个对象。在构造函数内处理避免了这一点。 – Damon 2011-04-21 10:56:53
@ zombie:有什么场景?从构造函数中抛出异常?构造函数失败?一个捕获异常的构造函数? – forsvarir 2011-04-21 10:57:21
异常处理和返回类型完全不同。当程序在构造函数中发现异常时,它会通过catch块[如果使用]或抛出调用方(main())将该异常抛出。在这种情况下,我们在构造函数和异常处理中都有catch块。一旦处理异常,构造函数/函数中的其余语句将开始执行。看下面的例子,
class A
{
public:
A(){
printf("Hi Constructor of A\n");
try
{
throw 10;
}
catch(...)
{
printf("the String is unexpected one in constructor\n");
}
printf("Hi Constructor of A\n");
}
~A(){
printf("Hi destructor of A\n");
}
};
int main()
{
try{
A obj ;
throw "Bad allocation";
}
catch(int i)
{
printf("the Exception if Integer is = %d\n", i);
}
catch(double i)
{
printf("the Exception if double is = %f\n", i);
}
catch(A *objE)
{
printf("the Exception if Object \n");
}
catch(...)
{
printf("the Exception if character/string \n");
}
printf("Code ends\n");
return 0;
}
这产生输出:
Start: Constructor of A
the String is unexpected one in constructor
End: Constructor of A
Hi destructor of A
the Exception if character/string
Code ends
你会捕获该异常调用代码,而不是在构造函数中。 – helpermethod 2011-04-21 10:48:10
异常不会以与返回值相同的方式返回,它们将堆栈跳到第一个适当的catch块,因此尽管您无法从构造函数返回值,但可以从中引发异常。 – forsvarir 2011-04-21 10:50:30
@Helper方法:如果您在构造函数中分配了内存,您肯定会想要在构造函数中捕获异常,以便您可以取消分配内存(然后重新抛出)。但更智能的是让对象只动态分配一个对象,所以你不需要执行这种手动清理。 – 2011-04-21 11:17:21