Implementation of C++ Exception Handling

1 Exception basic syntax
Insert picture description here
1) If there is an exception, create an exception object through the throw operation and throw it.
2) Embed the program segment that may throw an exception in the try block. Control passes through the normal sequence of execution to reach the try statement, and then executes the protection section within the try block.
3) If no exception is caused during the execution of the protection section, the catch clause following the try block is not executed. The program continues execution from the statement following the last catch clause following the try block.
4) The catch clauses are checked in the order they appear after the try block. The matching catch clause will catch and handle the exception (or continue to throw the exception).
5) If the matching processor is not found, the run function terminate will be called automatically, and its default function is to call abort to terminate the program.
6) Exceptions that cannot be handled can be thrown upwards using the throw syntax in the last branch of the catch.
Case 1:
Divide by zero Case int divide(int x, int y)
{ if (y == 0) { throw x; } return x/y; }





void main41()
{
try
{
cout << “8/2 = " << divide(8, 2) << endl;
cout << “10/0 =” << divide(10, 0) << endl;
}
catch (int e)
{
cout << “e” << " is divided by zero!” << endl;
}
catch(…)
{
cout << “未知异常” << endl;
}
cout << “ok” << endl;
system(“pause”);
return ;
}
案例2:
class A{};
void f(){
if(…) throw A;
}
void g(){
try{
f();
}catch(B){
cout<<“exception B\n”;
}
}
int main(){
g();
}
Throw A will penetrate the functions f, g and main, and reach the last line of defense of the system-trigger the terminate function.
This function calls the abort function that caused the operation to terminate.
The function of the last line of defense can be set by the programmer. Thereby stipulating its behavior before termination.
Modify the default behavior of the system:
The set_terminate function can be used to modify the default handler that cannot catch an exception, so that when an exception occurs, it will be processed by a custom function:
 void myTerminate(){cout<<“HereIsMyTerminate\n”; }
 set_terminate(myTerminate);
 The set_terminate function is declared in the header file exception, and the parameter is the function pointer void(*)().
Case 3:
 The constructor has no return type and cannot report the running status through the return value, so it only passes A non-functional mechanism approach, that is, the exception mechanism, to solve the error problem of the constructor.

7) The exception mechanism and the function mechanism do not interfere with each other, but the capture method is based on type matching. The capture is equivalent to the matching of the function return type, not the matching of the function parameters, so the capture does not need to consider the matching of multiple data types in a throwing. For
example:
class A{};
class B{};

int main()
{
try
{
int j = 0;
double d = 2.3;
char str[20] = “Hello”;
cout<<"Please input a exception number: ";
int a;
cin>>a;
switch(a)
{
case 1:
throw d;
case 2:
throw j;
case 3:
throw str;
case 4:
throw A();
case 5:
throw B();
default:
cout<<“No throws here.\n”;
}
}
catch(int)
{
cout<<“int exception.\n”;
}
catch(double)
{
cout<<“double exception.\n”;
}
catch(char*)
{
cout<<"char* exception.\n";
}
catch(A)
{ cout<<"class A exception.\n"; } catch(B) { cout<<"class B exception.\n"; } cout <<"That's ok.\n"; system("pause"); }//============================= ====== The catch code block must appear after the try, and multiple catch code blocks can appear after the try block to catch various types of throws. The exception mechanism is based on the principle: program operation is essentially the data entity doing some operations, so where an abnormal phenomenon occurs, there must be an error with an entity, and the data type corresponding to the entity is used as the basis for throwing and capturing . 8) Exception catching strictly follows the type matching The harshness of the type matching of exception catching can be comparable to the type matching of the template. It does not allow implicit conversion of compatible types. For example, throwing char type with int type cannot catch it. For example, the following code will not output "int exception.", so it will not output "That's ok." because the prompt to exit after an exception occurs int main(){ try{ throw'H'; }catch(int){ cout<<" int exception.\n”; }



















cout<<“That’s ok.\n”;
}

2 After the stack unwinding
exception is thrown, from entering the try block to before the exception is thrown, all objects constructed on the stack during this period will be automatically destructed. The order of destruction is opposite to the order of construction. This process is called unwinding of the stack.
class MyException {};

class Test
{
public:
Test(int a=0, int b=0)
{
this->a = a;
this->b = b;
cout << “Test 构造函数执行” << “a:” << a << " b: " << b << endl;
}
void printT()
{
cout << “a:” << a << " b: " << b << endl;
}
~Test()
{
cout << “Test 析构函数执行” << “a:” << a << " b: " << b << endl;
}
private:
int a;
int b;
};

void myFunc() throw (MyException)
{ Test t1; Test t2; cout << "Define two stack variables, test how stack variables are destructed after the exception is thrown" << endl; throw MyException(); } void main() { //After the exception is thrown, from entering the try block to before the exception is thrown, all objects constructed on the stack during this // will be automatically destructed. The order of destruction is opposite to the order of construction. //This process is called stack unwinding (unwinding) try { myFunc(); } //catch(MyException &e) //Cannot access exception object here catch(MyException) //Cannot access exception object here { cout << "MyException type exception received" << endl; } catch(…) { cout << "Unknown type exception" << endl; } system("pause"); return; } 3 exception interface declaration



























1) In order to enhance the readability of the program, all possible exception types can be listed in the function declaration, for example:
void func() throw (A, B, C, D); //This function func() can And can only throw exceptions of type ABCD and its subtypes.
2) If there is no exception interface declaration in the function declaration, the sub-function can throw any type of exception, for example:
void func();
3) A function that does not throw any type of exception can be declared as:
void func() throw( );
4) If a function throws an exception that is not allowed by its exception interface declaration, the unexpected function will be called. The default behavior of this function is to call the terminate function to terminate the program.

4 The life cycle of exception types and exception variables
1) Throw exceptions are typed and can be numbers, strings, and class objects.
2) Throw exceptions have types, and catch matches strictly according to the type.
3) Pay attention to the memory model of the abnormal object.
4.1 Traditional error handling

//File binary copy
int filecopy01(char *filename2, char *filename1)
{ FILE *fp1 = NULL, *fp2 = NULL; fp1 = fopen(filename1, “rb”); if (fp1 == NULL) { return 1 ; } fp2 = fopen(filename2, “wb”); if (fp1 == NULL) { return 2; } char buf[256]; int readlen, writelen; while ((readlen = fread(buf, 1, 256, fp1 ))> 0) //If the data is read, it is greater than 0 { writelen = fwrite(buf, 1, readlen, fp2); if (readlen != readlen) { return 3; } } fclose(fp1); fclose(fp2 ); return 0; }
























Test program
void main11()
{ int ret; ret = filecopy01("c:/1.txt","c:/2.txt"); if (ret !=0) { switch(ret) { case 1: printf ("Error opening source file!\n"); break; case 2: printf("Error opening target file!\n"); break; case 3: printf("Error copying file!\n"); break; default: printf("An unknown error occurred!\n"); break; } } } 4.2 throw int type exception /file binary copy void filecopy02(char *filename2, char *filename1) { FILE *fp1 = NULL, * fp2 = NULL; fp1 = fopen(filename1, “rb”); if (fp1 == NULL) {





























//return 1;
throw 1;
}
fp2 = fopen(filename2, “wb”);
if (fp1 == NULL)
{
//return 2;
throw 2;
}
char buf[256];
int readlen, writelen;
while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0
{
writelen = fwrite(buf, 1, readlen, fp2);
if (readlen != readlen)
{
//return 3;
throw 3;
}
}
fclose(fp1);
fclose(fp2);
return ;
}

4.3 throw character type exception
// binary copy of file
void filecopy03(char *filename2, char *filename1)
{ FILE *fp1 = NULL, *fp2 = NULL; fp1 = fopen(filename1, “rb”); if (fp1 == NULL) { throw "An error occurred while opening the source file"; } fp2 = fopen(filename2, "wb"); if (fp1 == NULL) { throw "Error opening the target file"; } char buf[256]; int readlen , writelen; while ((readlen = fread(buf, 1, 256, fp1))> 0) //If data is read, it is greater than 0 { writelen = fwrite(buf, 1, readlen, fp2); if (readlen! = readlen) { throw "Failed to copy files"; } } fclose(fp1); fclose(fp2); return;
























}

4.4 Throw class object type exception
//throw int type variable
//throw string type
//throw class type
class BadSrcFile
{ public: BadSrcFile() { cout << "BadSrcFile construct do "<<endl; } ~BadSrcFile() { cout << "BadSrcFile destructuring do "<<endl; } BadSrcFile(BadSrcFile & obj) { cout << "copy construction do "<<endl; } void toString() { cout << "aaaa" << endl; }
















};
class BadDestFile {};
class BadCpyFile {};;

void filecopy04(char *filename2, char *filename1 )
{
FILE *fp1= NULL, *fp2 = NULL;
fp1 = fopen(filename1, “rb”);
if (fp1 == NULL)
{
//throw new BadSrcFile();
throw BadSrcFile();
}

fp2 = fopen(filename2, “wb”);
if (fp1 == NULL)
{ throw BadDestFile(); } char buf[256]; int readlen, writelen; while ((readlen = fread(buf, 1, 256, fp1 ))> 0) //If the data is read, it is greater than 0 { writelen = fwrite(buf, 1, readlen, fp2); if (readlen != readlen) { throw BadCpyFile(); } } fclose(fp1); fclose (fp2); return; } main test case
















//Conclusion://The C++ compiler generates objects through throw, and the C++ compiler executes the corresponding catch branch, which is equivalent to a function call, passing the actual parameters to the formal parameters.
void main11()
{ try { //filecopy02("c:/1.txt","c:/2.txt"); // filecopy03("c:/1.txt","c:/2.txt ”); filecopy04(“c:/1.txt”,“c:/2.txt”); } catch (int e) { printf("An exception occurred: %d \n", e); } catch (const char * e) { printf("An exception occurred: %s \n", e); } catch (BadSrcFile *e) { e->toString(); printf("An exception occurred: an error occurred while opening the source file!\n" ); } catch (BadSrcFile &e) { e.toString(); printf("An exception occurred: An error occurred while opening the source file!\n"); } catch (BadDestFile e) {


























printf("An exception occurred: An error occurred while opening the target file!\n");
}
catch (BadCpyFile e)
{ printf("An exception occurred: An error occurred during copy!\n"); } catch(…) //Catch the fish that slipped through the net { printf("An unknown exception has occurred! Catch the fish that slipped through the net\n"); } //class BadSrcFile {}; //class BadDestFile {}; //class BadCpyFile {};; }









Guess you like

Origin blog.csdn.net/it_xiangqiang/article/details/109214668