Difficulty:
Is there an exception in your code? As the most controversial thing in C , even if you use it, do you think of an abnormal?
If you want to judge whether an object is constructed, we can use the following three methods.
1,
Struct a
{
A (int & i)
{
// Other code
IF (constrained)
i = 0;
Else
i = 1;
}
}
INT I;
A a (i);
IF (i == 0)
COUT << "Construct Failure" << Endl;
2,
Class A
{
PUBLIC:
A ()
{
// Other code
IF (constrained)
Isok_ = false;
Else
ISOK_ = TRUE;
}
BOOL ISOK () Const
{Return Isok_;}
Private:
BOOL ISOK_;
}
A a a;
IF (! a.isek ())
COUT << "Construct Failure" << Endl;
3,
Class my_exception: public std :: eXception {};
Struct a
{
A ()
{
// Other code
IF (constrained)
Throw my_exception ();
}
}
Try
{
A a a;
}
Catch (MY_EXCEPTION & EX)
{COUT << "Construction Failure" << Endl;}
Three ways to find out, let's make a simple analysis.
The first, the constructor provides a marker variable for returning an error, although it can determine whether the structure is successful, but this excess variable is more like a cumbersome.
The second, there is no ambiguity on the constructor. But it does not reduce complexity. More importantly, it has a common problem with the first method, that is, the destructor will be properly called. In other words, such an object construct failure is not supported by the language, but the programmer's own logic specification.
Third, this is completely without the problem of the above two methods, and there is an abnormality in the constructor, it means that this object is not constructed, which is supported by the language, so that the destructor of Class A Will not act on object a. This feature allows us no longer worry about this type of security.
In some functions, we can return an error code by values, but in some cases this type of method does not use so, so we can consider exceptions.
From the above performance, there is no complexity of exception. However, when you encounter resource management, there will be many things may be ignored by us.
Void test ()
{
INT * P = new int;
// Other code
Delete P;
}
If the intermediate code throws an exception, the best situation is the memory leak and bringing unsafe factors. We should join an abnormal handling
Void test ()
{
INT * P = NULL;
Try
{
P = new int;
// Other code
}
Catch (...)
{
Delete P;
Throw; // Abnormal neutral, guarantee the behavior of the previous version TEST function
}
Delete P;
}
But this may not be the coolest solution. We can take advantage of RAII skills. To simplify this operation
Template
Class auto_new
{
PUBLIC:
Auto_new (): PTR_ (NULL)
{
Try
{
PTR_ = New T;
}
Catch (std :: bad_alloc)
{
// abnormal processing
}
}
~ auto_new ()
{
Delete PTR_;
}
Operator t * () {return PTR_;
Private:
T * PRT_;
}
Void test ()
{
Auto_new
// Other code
}
This doesn't have to worry about the resource recovery problem brought about by abnormalities. Of course, for simple resources, we can use auto_ptr <>.
Perhaps everyone will think that such practices have not reduced complexity, which seems to increase the workload. Yes, but this code can make us more assured.
An exception is not perfect, it has a lot of defects itself, such as its operating cost, if the normal control structure can handle errors, then it should not use an exception. An exception is that when a portion has an abnormal situation, then we can notify another part by anomalous. For example, when an exception occurs, then we can transfer this anomaly layer to the call point of the function, while other error handling methods are not so convenient. Although an exception can be passed in two parts, it is not cross thread, we cannot pass anomalies between two threads. For example, the following code is incorrect.
DWORD CALLBACK THREADFUNC (VOID *)
{
// Other code
Throw int (); // throw an abnormality
}
Int main () {
Try
{
DWORD TID;
Handle HDL = CreateThread (NULL, 0, & Threadfunc, NULL, 0, & TID);
SLEEP (500);
CloseHandle (HDL);
}
Catch (...)
{Cout << "catch" << endl;
}
Threadfunc throwing abnormally we could not receive it. This also illustrates a problem that when we don't determine if the code in the thread function will throw an exception, we must join the TRY block to ensure exception security. For example, the above code should be written as the following
DWORD CALLBACK THREADFUNC (VOID *)
{
Try
{
// Other code // Not sure if this will throw an exception
}
Catch (...)
{}
}
Int main () {
DWORD TID;
Handle HDL = CreateThread (NULL, 0, & Threadfunc, NULL, 0, & TID);
SLEEP (500);
CloseHandle (HDL);
}
// the end