我们可以在构造函数中放置异常处理 [英] Can we put exception handling inside the constuctor

查看:58
本文介绍了我们可以在构造函数中放置异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一次采访中得到了这个问题。问题是,我们可以在构造函数中进行异常处理,从构造函数中抛出异常是否安全。



我通过在构造函数中放置一个try catch块来尝试示例代码,但我没有得到任何错误。任何人都可以解释一下这个

I got this question in an interview.The question is, can we have exception handling in the constructor and is it safe to throw an exception from the constructor.

I tried a sample code by putting a try catch block in the constructor but I didnt get any error.Can any one please explain about this

推荐答案

阅读我的评论这个问题,从那里继续。请记住,构造函数也是函数。因此,当您创建自定义构造函数逻辑时,您基本上是在尝试设置基础对象。如果他们遇到一些错误并且只能在一个条件下工作,那么是的。你还需要在构造函数上下文中处理异常。



但是(IMO)它将没有用。假设您正在为作为硬件控制器的对象编写构造函数;例如闪存驱动器。构造函数必须加载其他基础对象,例如通过端口连接。



Read my comment to the question, continuing from there. Remember, constructors are also functions. So, when you create a custom constructor logic you are basically trying to set up the underlying objects. If they are exposed to some errors and would work in a condition only, then yes. You need to handle the exceptions in the constructor context also.

But (IMO) it would be of no good. Suppose you are writing a constructor for an object that acts as the controller for your hardware; flash drive reader for instance. The constructor has to load the other base objects, such as connection over the ports.

public:
  FlashReader() {
    // Construct the stream reader for the port
    _streamReader = streamreader::Reader(); // <-- Here
  }





假设读者不工作,无论出现什么问题。添加try catch块对你没有帮助。只是为了防止应用程序崩溃。否则,添加try catch块将无法以任何方式帮助您。





Suppose, reader doesn't work, no matter of what problem. Adding a try catch block won't help you. It would be just as to prevent the application from breaking, only. Otherwise, adding a try catch block won't help you out in any way.

public:
  FlashReader() {
    // Construct the stream reader for the port
    try {
       _streamReader = streamreader::Reader(); // <-- Here
    } catch (std::exception e) {
       // No difference made. 
    }
  }





这就是为什么,尽管在C ++中写一些是合法的尝试捕获块。但是,为了什么?这是你需要回答的问题。它真的重要,或者是否值得添加一个try catch块,或者只是另一个奇特的事情来维护内存中的死程序。 :-)



为了更清楚地了解可能由此类行为引起的问题,请阅读Sergey的解决方案3 。它会向您显示图像,以及此模式可能需要的候选项。



另外,你的术语安全是什么意思?线程安全还是什么?数据安全是关于实例成员的概念。如果构造函数抛出异常,这意味着没有创建实例,因此不会讨论安全问题。我会说,从构造函数中抛出异常将是一个很好的例外。因为,它会通知用户并中断程序,而不是将其保留在内存中以为自定义错误消息创建新堆栈。



That is why, although it is legal in C++ to write the try catch block. But, for what? That is the question you need to answer. Does it really matter, or is it worthy to add a try catch block, or is it just another fancy thing to maintain a dead program in the memory. :-)

For a more clearer image of the problem that might be caused with this kind of behavior, read Solution 3 by Sergey. It shows you the image, and what are the possible candidates that might be expected with this pattern.

Also, what did your term safe means? Thread-safe or what? Safety of data is a concept about instance members. If a constructor throws an exception that means no instance was created, thus no discussion to take place about safety. Throwing exception from a constructor would be a good one, I'd say. Because, it would notify the user and break the program, instead of keeping it there in the memory to create a new stack for the custom error message.


有看一下这个页面:异常和错误处理 [ ^ ]。
Have a look at this page: "Exceptions and Error Handling"[^].


此外解决方案1:答案可能更确定:是和否。 :-)



首先,从您的问题来看,目前尚不清楚您在谈论什么。你在谈论处理异常,而在其他地方你正在谈论抛出。让我们先讨论抛出。



当然,可以从构造函数中抛出异常,然后以安全的方式继续执行程序。但这是一个很好的编程习惯吗?是的,不是;如果不深入了解自己的设计和后果,它可能会非常糟糕,但对于精心策划和设计的东西来说,这可能并不坏。因此,该技术应该首先成为一个疑问的对象。



基本的争议​​是这样的:结构化异常处理机制是将所有内容恢复到第一点的时间机器尝试堆栈。但是还原了什么?只有堆栈和堆栈对象,当然,不是副作用。分配堆和构造的堆和对象只是这样的网站效果之一,但它可以是其他任何东西。



例如,让我们说,你有一个构造函数它在堆上创建了一些其他对象,并且每个对象也在堆上创建了一些其他对象。而且,更重要的是,您的类也是此链的一部分,由其他类使用,您的对象也可以在堆上创建。这是一张非常典型的图片。通常,您可以在堆栈的任何位置处理异常,并可以自由地抽象出异常(其位置,某些细节等)。使用堆,您可以根据抛出异常的方式和位置来创建代码。真正的问题在于我们假设的父对象(当你为外部开发一些类时,它的使用应该被认为是假设的):你最终可能会得到一半构造的对象,无法找到目的来恢复堆(也就是说,内存泄漏最多)。我再说一遍:堆只是这个问题最典型的例子。



当然,如果没有副作用,你可以没事。即使有堆,如果你完全控制两种情况下的情况,例外,没有它。这导致我们在构造函数中完成异常处理的问题。



如果抛出一些异常是一些构造函数并在同一个构造函数中捕获它会怎么样? (我再说一遍:你的问题不清楚你是否意味着这个)?你将遇到上面讨论的所有相同的问题,只有你有更多的控制权,并且实际上可以解决两种情况下正确构造的问题(处理异常与否)。但这样的目标看起来很奇怪。如果处理构造函数执行之外的异常,您希望遇到没有创建对象的情况,并且您的执行上下文就像您从未尝试过一样。通过在构造函数内部进行处理,您可以全部处理它,并在抛出构造函数中更深的异常后实际创建一个对象。我怀疑这种设计的可能原理。但一般来说,在本地处理异常是一个非常糟糕的主意。例外旨在将常规执行与异常隔离开来。因此,它为您提供了很少的好处,您可以在每个堆栈上累积许多可能的异常,并完全处理。你必须战略性地选择那些点,当然,它们并不是每个函数都抛出异常。



另见我过去的答案:

C#构造函数中的异常会导致来电者分配失败吗? [ ^ ],

在操作系统中存储.net例外 [ ^ ],

未处理的例外:访问冲突 [ ^ ]。



-SA
In addition to Solution 1: The answer could be more certain: yes and no. :-)

First of all, from your question, it is not clear what you are talking about. You are talking about handling exceptions, and in other place you are talking about throwing. Let's discuss throwing first.

Of course, it is possible to throw an exception from a constructor and then continue execution of the program in a safe way. But is it a good programming practice? Yes and no; without deep understanding of one's own design and consequences, it will likely be very bad, but it can be not bad for something well planned and designed. So, the technique should first become an object of a doubt.

The fundamental controversy is this: structured exception handling mechanism is the time machine which reverts everything to the first point of try up the stack. But what is reverted? Only the stack and the stack object, and, of course, not the side effects. The heap and the objects allocating heap and constructed is just one of such site effects, but it can be anything else.

For example, let's say, you have a constructor which creates some other objects on heap, and each of those objects also creates some other objects on heap. And, more importantly, your class is also a part of this chain, is used by some other class, and your object can also be created on heap. This is a very typical picture. Normally, you can handle an exception anywhere up the stack and have a freedom of abstracting out the exception (its location, some detail, and so on). With heap, you make your code depending on how and where the exception is thrown. The real problem is with our hypothetical "parent object" (when you develop some class for external, its use should be considered hypothetical): you can end up with half-constructed set of objects, with no way to find ends to revert the heap (that is, memory leak at best). I repeat: heap is just the most typical example of the problem.

But of course, without the side effects you can be fine. Even with the heap, if you fully control the situation in both cases, with the exception and without it. Which leads us to the problems of full exception handling inside a constructor.

What if you throw some exception is some constructor and catch it in the same constructor? (I repeat: it's not clear from your question if you meant that or not)? You will have all the same problems discussed above, only you have more control and can practically resolve the problem of correct construction in both situations (exception handled and not). But such goal would look weird. In case of handling exceptions outside of the constructor execution, you want to come to the situation where you have the object not created, and your execution context in the position as if you never tried. With handling inside a constructor, you can have it all handled, and actually created an object after an exception deeper in a constructor was thrown. I doubt the possible rationale of this design. But generally, handling exceptions too locally is a pretty bad idea. Exceptions are designed to isolate "regular" execution from exceptional. Therefore, it gives you the benefit of having very few points where you accumulate many possible exceptions on every stack, and handle the altogether. You have to strategically chose those points, and, of course, they are not in each function throwing exception.

See also my past answers:
Does Exception in C# Constructor Cause Caller Assignment to Fail?[^],
where was stored .net exceptions in operating system[^],
Unhandled Exception : Access Violation[^].

—SA


这篇关于我们可以在构造函数中放置异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆