08自定义异常类的两个例子
前提:
自定义异常两步曲:
1)提供一个接收char*的构造函数。
2)重写异常基类exception的两个虚函数-what()和析构(返回值类型忘记可以查看基类)
注意:what()虚函数的两个const必须写才能与父类的what对应,否则不能实现多态。
1 例子1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdexcept>
using namespace std;
/*
自定义异常两部曲
1)提供一个接收char*的构造函数
2)重写异常基类exception的两个虚函数-what()和析构(返回值类型忘记可以查看基类)
*/
class MyException1:public exception {
public:
MyException1(const char* str) {
error = new char[strlen(str) + 1];
strcpy(error, str);
}
const char* what()const { // what()虚函数的两个const必须写才能与父类的what对应 否则不能实现多态
return this->error;
}
~MyException1(){
if (this->error != NULL) {
delete[] this->error;
this->error = NULL;
}
}
// 凡是有类指针成员的 都写拷贝构造和等号运算符
MyException1(const MyException1 &other) {
error = new char[strlen(other.error) + 1];
strcpy(error, other.error);
}
MyException1& operator = (const MyException1 &other) {
if (this == &other) {
return *this;
}
if (this->error != NULL) {
delete[] this->error;
this->error = NULL;
}
error = new char[strlen(other.error) + 1];
strcpy(error, other.error);
return *this;
}
private:
char *error;
};
class Person {
public:
Person(int age){
if (age < 0 || age>100) {
throw MyException1("自定义异常"); // 抛出自定义异常
}
this->m_age = age;
}
private:
int m_age;
};
int main() {
try{
Person(101);
}
catch (exception &e){ // 用基类接收自定义子类
cout << e.what() << endl;
}
return 0;
}
2 例子2,这里不适用老师讲的,太简单了,用练习题做例子。这里的数组类我使用了模板进行实现。
要求:
设计一个数组类 MyArray,重载[]操作,数组在创建时,对数组的容量进行有效检查:
1)index < 0 抛出异常eNegative;
2)index = 0 抛 出 异 常 eZero ;
3)index>1000抛出异常eTooBig ;
4)index < 10 抛出异常eTooSmall;
5)eSize类是以上类的父类,实现有参数构造、并定义virtual void printErr()输出错误。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdexcept>
using namespace std;
/*
源码的异常基类写得好,他直接在里面用指针记录错误信息,
其它子类只需调用基类的复制函数更改该指针的错误信息为子类的即可。
这里只按要求实现功能。
*/
// 异常父类
class eSize {
public:
virtual void printErr() {
cout << "eSize error" << endl; // 调用父类异常
}
virtual ~eSize(){}
};
// eNegative
class eNegative : public eSize {
public:
eNegative(){
m_error = NULL;
}
eNegative(const char* error){
m_error = new char[strlen(error) + 1];
strcpy(m_error, error);
}
eNegative(const eNegative &other) {
m_error = new char[strlen(other.m_error) + 1];
strcpy(m_error, other.m_error);
}
eNegative& operator=(const eNegative& other) {
if (this == &other) {
return *this;
}
if (this->m_error != NULL) {
delete[] m_error;
m_error = NULL;
}
m_error = new char[strlen(other.m_error) + 1];
strcpy(m_error, other.m_error);
return *this;
}
virtual void printErr() {
cout << (this->m_error? this->m_error : "eNegative error") << endl; // 调用子类异常 默认报这个错误
}
~eNegative() {
if (m_error != NULL) {
delete[] m_error;
m_error = NULL;
}
}
private:
char *m_error;
};
// eZero
class eZero : public eSize {
public:
eZero() {
m_error = NULL;
}
eZero(const char* error) {
m_error = new char[strlen(error) + 1];
strcpy(m_error, error);
}
eZero(const eZero &other) {
m_error = new char[strlen(other.m_error) + 1];
strcpy(m_error, other.m_error);
}
eZero& operator=(const eZero& other) {
if (this == &other) {
return *this;
}
if (this->m_error != NULL) {
delete[] m_error;
m_error = NULL;
}
m_error = new char[strlen(other.m_error) + 1];
strcpy(m_error, other.m_error);
return *this;
}
virtual void printErr() {
cout << (this->m_error ? this->m_error : "eZero error") << endl; // 调用子类异常 默认报这个错误
}
~eZero() {
if (m_error != NULL) {
delete[] m_error;
m_error = NULL;
}
}
private:
char *m_error;
};
// eTooBig
class eTooBig : public eSize {
public:
eTooBig() {
m_error = NULL;
}
eTooBig(const char* error) {
m_error = new char[strlen(error) + 1];
strcpy(m_error, error);
}
eTooBig(const eTooBig &other) {
m_error = new char[strlen(other.m_error) + 1];
strcpy(m_error, other.m_error);
}
eTooBig& operator=(const eTooBig& other) {
if (this == &other) {
return *this;
}
if (this->m_error != NULL) {
delete[] m_error;
m_error = NULL;
}
m_error = new char[strlen(other.m_error) + 1];
strcpy(m_error, other.m_error);
return *this;
}
virtual void printErr() {
cout << (this->m_error ? this->m_error : "eTooBig error") << endl; // 调用子类异常 默认报这个错误
}
~eTooBig() {
if (m_error != NULL) {
delete[] m_error;
m_error = NULL;
}
}
private:
char *m_error;
};
// eTooSmall
class eTooSmall : public eSize {
public:
eTooSmall() {
m_error = NULL;
}
eTooSmall(const char* error) {
m_error = new char[strlen(error) + 1];
strcpy(m_error, error);
}
eTooSmall(const eTooSmall &other) {
m_error = new char[strlen(other.m_error) + 1];
strcpy(m_error, other.m_error);
}
eTooSmall& operator=(const eTooSmall& other) {
if (this == &other) {
return *this;
}
if (this->m_error != NULL) {
delete[] m_error;
m_error = NULL;
}
m_error = new char[strlen(other.m_error) + 1];
strcpy(m_error, other.m_error);
return *this;
}
virtual void printErr() {
cout << (this->m_error ? this->m_error : "eTooSmall error") << endl; // 调用子类异常 默认报这个错误
}
~eTooSmall() {
if (m_error != NULL) {
delete[] m_error;
m_error = NULL;
}
}
private:
char *m_error;
};
// 自定义数组类
// T代表一个类型 MyArray<T>代表一个数组
template<class T>
class MyArray {
public:
// 不写无参构造就是不支持默认开辟容量的数组
//有参 创建capacity大小的数组
MyArray<T>(int capacity){
if (capacity < 0) {
throw eNegative("数组容量小于0");
}
else if (capacity == 0) {
throw eZero("数组容量为0");
}
else if (capacity < 10) {
throw eTooSmall("数组容量太小");
}
else if (capacity > 1000) {
throw eTooBig("数组容量太大");
}
else
{
mCapacity = capacity;
mSize = 0;
mAddr = new T[capacity];
}
}
//拷贝 (注:参数是数组,不是T)
MyArray<T>(const MyArray<T> &array){
mCapacity = array.mCapacity;
mSize = array.mSize;
// 先开辟内存再赋值
mAddr = new T[mCapacity];
for (int i = 0; i < mSize; i++) {
mAddr[i] = array.mAddr[i];
}
}
//等号
MyArray& operator=(const MyArray<T> &array) {
if (this == &array) {
return *this;
}
if (this->mAddr != NULL) {
delete[] mAddr;
mAddr = NULL;
}
mCapacity = array.mCapacity;
mSize = array.mSize;
// 先开辟内存再赋值
mAddr = new T[mCapacity];
for (int i = 0; i < mSize; i++) {
mAddr[i] = array.mAddr[i];
}
return *this;
}
/*
返回值为引用(即返回的是该值本身)
1)用普通值接相当于值传递
2)用引用接也相当于值传递 但是当该返回值本身为栈局部变量 则非常容易出错
*/
// 重载[]
T& operator[](int index) {
return this->mAddr[index];
}
// 添加元素
void PushBack(T& data) {
if (this->mSize >= this->mCapacity) {
return;
}
this->pAddr[this->mSize] = data;
this->mSize++;
}
~MyArray() {
if (this->mAddr != NULL) {
delete[] this->mAddr;
}
}
private:
int mCapacity;// 数组容量
int mSize; // 数组元素大小
T* mAddr; // 指向内存首地址 即管理该数组内存
};
void test01() {
try {
MyArray<int> arr(1001);
}
catch (eSize &e) { // 使用基类来接收所有子类的异常
e.printErr();
}
}
int main() {
test01();
return 0;
}