C++ exception mechanism

C++ exception mechanism

Initial use of exception handling

We enclose the block of code that may cause an exception with a try block, which we call a safe segment, and then catch the possible exception after it.

Note: At least one exception must be caught or an error will occur. If the exception is caught once, it won't be caught again unless it is thrown again, even though the catching code probably does nothing. Once an exception is thrown, the program will immediately jump to the catch code corresponding to the try block, and will not execute the rest of the try block.

#include <iostream>
#include <string>
using namespace std;
//Specify all possible throw types
void fun1(const char* dest, const char* res)throw(int,string*,float) {
	FILE *f1, *f2;
	f1 = f2 = NULL;
	fopen_s(&f1, res, "rb");//binary read only
	if (f1 == NULL) {
		throw new string("Failed to open source file!");
	}
	fopen_s(&f2, dest, "wb");//binary write only
	if (f2 == NULL) {
		throw new string("target file failed to open!");
	}
	char buffer[64];
	int readsize, writesize;
	while (readsize = fread(buffer, 1, 64, f1) > 0) {//There is data to read
		writesize = fwrite(buffer, 1, 64, f2);
		if (readsize != writesize) {
			throw new string("Failed to read file!");
		}
	}
	fclose(f1);
	fclose(f2);
}
void fun2(const char* dest, const char* res) {
	try {
		fun1(dest, res);
	}
	catch(...) {//Catch any kind of exception
		throw;
		cout << "fun2 exception catch" << endl;
	}
}
int main(void) {
	try {
		cout << "Prepare for exception catch" << endl;
		fun2("dest.txt", "res.txt");
		cout << "Exception catch completed" << endl;
	}
	catch (int error) {
		
	}
	catch (string* error) {
		printf("abnormal:%s", error->c_str());
	}
	catch (float error) {

	}
	return 0;
}

Exception handling interface declaration

  1. List all possible exception types in the function declaration
  2. If no exception interface declaration is included, it can throw any type by default
  3. The type in the exception interface declaration cannot be thrown, otherwise an error will be reported
  4. If you don't want to throw any type, you can directly define it as empty
void fun1(const char* dest,const char* res)throw(){}

Exception Type Lifecycle

In general, the lifetime of local variables will be destructed immediately after leaving the function, but anonymous objects can be destructed together with the parameters in the catch block after the end of the catch block.

Precautions

  1. The best way to throw class types is to use reference types to capture and throw anonymous objects.
  2. If it is dynamically allocated memory, return the pointer directly, but remember to delete.
  3. The essence of returning a string is actually returning a pointer, which is actually a value transfer.
  4. References and normal parameter types cannot coexist, just like function calls.

exception class

An exception can also be counted as a class, that is, we can directly define an error base class, and then return a specific error subclass from the safe segment. Then capture the reference of the base class or the pointer of the base class from the catch to complete the polymorphism.

#pragma once
#include <iostream>
class abnormal {
public:
	abnormal(int size) { this->size = size; }
	virtual ~abnormal() {};
	virtual void desc()const = 0;
protected:
	int size;
};
class negativeabnormal :public abnormal {
public:
	negativeabnormal(int size) :abnormal(size) {}
	~negativeabnormal() {};
	void desc()const override {
		std::cout << "negativeabnormal!\nsize:" << size << std::endl;
	}
};
class boundaryabnormal :public abnormal {
public:
	boundaryabnormal(int size) :abnormal(size) {}
	~boundaryabnormal() {};
	void desc()const override {
		std::cout << "boundaryabnormal!\nsize:" << size << std::endl;
	}
};

Return the object of the subclass in the security segment, and then use the base class reference to capture it

template<typename T>
Vector<T>::Vector(int size) {
	/*if (size > 0) {
		this->size = size;
	}
	else {
		this->size = 64;
	}
	arr = new T[this->size];*/
	if (size < 0) {
		this->size = 64;
		throw negativeabnormal(size);
	}
	else if (size > BOUNDARY) {
		this->size = BOUNDARY;
		throw boundaryabnormal(size);
	}
	else {
		this->size = size;
	}
	arr = new T[this->size];
}


	try {//secure segment
		Vector<int> v1(100);
		for (int i = 0; i != 10; ++i) {
			v1[i] = i + 1;
		}
		for (int i = 0; i != 10; ++i) {
			cout << v1[i] << " ";
		}
	}
	catch (const abnormal& object) {
		object.desc();
		cout << endl;
	}

Exception classes in the standard library

The standard library also defines some exception classes for us to use, the more common ones are bad_alloc and out_of_range subclasses, where bad_alloc is automatically called by the system when space allocation fails. Remember to include the corresponding header file exception and stdexcept

Tags: Algorithm C++ programming language

Posted by Humpty on Wed, 19 Oct 2022 10:57:04 +0530