C ++ usage exceptions

Source: Internet
Author: User

The error handling method has always been a headache. Recently, when I was writing a program, I came up with a set of exception principles, which were recorded as my experiences.

1. Use objects to manage resources

First, the resources to be released should be managed with objects, and the architecture of C ++ should be used to avoid resource leakage. For example, Win32 handles must be closed after they are used up.

Class
File {

Protected
:

String
M_filepath;
Handle m_file;

Public
:
File (
Const
 
String
Filepath );

~
File ();
};

File: file (
Const
 
String
Filepath ){
M_filepath
=
Filepath;
M_file
=
Openfile (...);

If
(Invalid_file
=
M_file)

Throw
Runtime_error (
"
Open File failed.
"
);
}

File ::
~
File (){
Closehanle (m_file );
}

In this way, the resources can be released to the release function, so that no worries can be raised when an exception is thrown.

2. Exception object

The C ++ language contains an exception system. The root class is exception, and the sub-classes include runtime_error, logic_error, invalid_argument, and so on ..., some large software will define a set of exception systems, but the function is similar to that of C ++ exception objects. Some methods may be expanded as needed, but I think C ++ is enough for general software. Some software also defines exception classes with message stacks. The original intention may be to describe exceptions in as much detail as possible. In my opinion, this is actually unnecessary, the caller only needs to know whether the method he or she calls is successful, and does not need to know what is going on in the inner layer (Information Hiding). Then, the inner layer should process the errors, the exception message should not be streamed out again. As for the exception message, it should be output layer by layer with the invocation of the lamp instead of being left to the outermost side before printstacktrace ()..., this issue is further discussed below.

3. Always create valid objects

If an object is constructed successfully, it must be complete and its status is correct, like the file class above. If openfile In the constructor fails, an exception is thrown to prevent the creation of this object. This ensures that if the file object is successfully created, it must have opened a file and can be read and written, it does not mean that the file structure is successful, but the file is not opened. In the future, file not open will occur when you call the function. The Destructor is not required.
If (m_file)
Closehandle (m_file );
Because the object must be valid!

However, it is not easy to maintain the state that the object must be valid. Sometimes an error occurs when writing a member function, which may damage the state of the object. Therefore, you must use the exception free thinking to write the program, see exceptional C ++.

4. If no exception exists, the business is successful.

If a function has a result in the business sense, the return value is used to pass the result and an exception is used to pass the error.
If a function has no result in the business sense, the void is returned and an error is passed with an exception.
Do not use the returned error code or an invalid object to specify that the operation fails.

For example, a file object has a member function to obtain the file size.

Size_t file: getfilesize (){

Try
{
Fseek (seek_end,
0
,...);
Size_t s
=
Ftell (....);

If
(
-
1
 
=
S)

Throw
Runtime_error (
"
Ftell failed
"
);

Return
S;
}

Catch
(...){

//
Return-1;
//
Don't do this !!!



Throw
Runtime_error (
"
Failed to get file size: Unknown exception.
"
);
//
This should be the case


}
}

Or

Void
Usermanager: adduser (User user ){

Try
{

//
If an exception occurs when you join a user, an exception is thrown.


}

Catch
(...){

Throw
Runtime_error (
"
Failed to add user: Unknown exception
"
);
}
}

The caller only needs

Void
Bussiness: dobussiness1 (){

Try
{
Usermanager
Usermanager. adduser (user (
"
Lingch
"
));


//
If the program runs successfully here, everything is normal, and no error is returned. The new user "lingch" must have been added successfully.

//
If a user fails to be added, the program will be included in the catch below.


//
Do other process...


}

Catch
(Exception
&
Ex ){
Cerr
<
Ex. What ()
<
Endl;

Throw
Runtime_error (
"
Do business1 failed.
"
);
}

Catch
(...){

//
...


}
}

In this way, the code in the try block will be very clean, and only the Business Code will be included. All exceptions will be handled in the Catch Block.

5. Exception Handling

Only the business is processed in the try block. All exceptions are stored in the Catch Block for processing. Exception messages are used to transmit exception information.

Void
Usermanager: adduser (User user ){

Try
{
Log4cplus_info (logger,
"
Start adding user.
"
);

Log4cplus_debug (logger,
"
Adding User: Step 1.
"
);

//
... Step 1, assuming there is no exception



Log4cplus_debug (logger,
"
Adding User: Step 2.
"
);

//
... Step 2. Assume that an exception occurs and the runtime_error object is thrown.



Log4cplus_debug (logger,
"
Adding User: Step 3.
"
);

//
... Step 3. If an exception occurs in step 2, it should not be executed again.



Log4cplus_info (logger,
"
Adding User done.
"
);
}

Catch
(Exception
&
Ex ){
//
The runtime_error object thrown during step 2 is obtained.


Log4cplus_error (logger, Ex. What ());
//
This is written to the log and the specific error cause must be written,

//
That is, the information transmitted when an exception is thrown in step 2,

//
In this way, the log will reflect the actual error of the service (within the try block,

//
A message stack is formed when the stack is expanded layer by layer (So exceptions with the message stack do not work)

//
Of course, logs are not necessarily files, but can also be output on the console.




Throw
Runtime_error (
"
Failed to add user.
"
);
//
This is reported to the caller. You do not need to write the specific error cause.

//
All you need to do is to notify the caller of failed services.


}

Catch
(...){
Log4cplus_error (logger,
"
Unknown exception
"
);

Throw
Runtime_error (
"
Failed to add user.
"
);
}
}

In the Catch Block, throw runtime_error does not need to let the external caller know what the error is? If the exception is thrown by the current layer, it only reflects some errors in the current layer. If the exception is thrown by the inner layer and can be processed and restored by the current layer, A try block should be embedded in step 2 to process the block and recover the block, instead of flowing to the Catch Block. If the block is thrown in the inner layer and cannot be processed, it does not make sense to reflect the errors in the inner layer. Do the callers of the outer layer have to pay attention to whether the exception is divided by 0 within N layers? :-) The code at the current layer only reports whether the current layer is successful or not, instead of the status of the inner layer. Exceptions at the inner layer should be handled and cannot be routed to the outer layer, in this way, each role should be embedded to hide the inner layer as a principle to avoid abnormal transmission across the call layer.

6. Effect

Through such processing, if an exception occurs, the log should contain an exception message stack, and each function's try block contains only clean business code, all exceptions are handled by the Catch Block :-)
In my opinion, the most difficult part is how to ensure that an object is exception free.
In addition, exception efficiency is used.

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.