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;
}

08自定义异常类的两个例子(例子2为异常在继承中的应用,且包含模板类的应用)相关推荐

  1. python类的属性前加上双下划线_在Python中使用双下划线防止类属性被覆盖

    在使用Python编写面向对象的代码时,咱们会经常使用"继承"这种开发方式.例以下面这一段代码:python class Info: def __init__(self): pas ...

  2. 问模板函数、函数模板,模板类、类模板的区别的问题?

    问模板函数.函数模板,模板类.类模板的区别的问题? - 赵保龙 - 博客园 问模板函数.函数模板,模板类.类模板的区别的问题? 在C++中有好几个这样的术语,但是我们很多时候用的并不正确,几乎是互相替 ...

  3. 模板类与类模板、函数模板与模板函数等的区别

    在C++中有好几个这样的术语,但是我们很多时候用的并不正确,几乎是互相替换混淆使用.下面我想彻底辨清几个术语,这样就可以避免很多概念上的混淆和使用上的错误. 这几个词是: 函数指针--指针函数 数组指 ...

  4. 模板函数与函数模板 类模板和模板的说明

    一,模板的概念. 引入模板的原因: 我们已经学过重载,对重载函数而言,C++的检查机制能通过函数参数的不同及所属类的不同.正确的调用重载函数.例如,为求两个数的最大值,我们定义MAX()函数需要对不同 ...

  5. 【C++ 语言】面向对象 ( 模板编程 | 函数模板 | 类模板 )

    文章目录 函数模板 类模板 代码示例 函数模板 1. 模板编程 : 类似于 Java 中的泛型编程 ; ① 函数模板 : 对应着 Java 中的泛型方法 ; ② 类模板 : 对应 Java 中的泛型类 ...

  6. C++使用模板类实现简单的人事管理系统

    写在前面 这几天我一直在做我们<C++与数据结构>课程的大作业--c++人事管理系统.在写的过程中遇到了很多困难,也让我深刻地体会到"纸上得来终觉浅,绝知此事要躬行". ...

  7. C++深入理解模板类

    ++的语法真是太多了 首先,栈可以使用指针压栈吗? 当然可以,这里写一个简单的栈 提到指针,可能会想到字符串,我们可以有以下几种传入 string str; 最简单的传入,得益于C++提供的强大的st ...

  8. 【c++】因模板类导致的 LNK2019 错误:“ 无法解析的外部符号 ” 详解

    最近在做项目的时候用到了模板类 果不其然出现了那个错误 LNK2019:无法解析的外部符号 网上百度到的结果繁花怒放,大多数不符合我的需求,故自己研究了下C++的模板类规则,试图找出问题所在 ---- ...

  9. 在保护继承中基类的共有成员_C++面向对象:C++ 继承

    面向对象程序设计中最重要的一个概念是继承.继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易.这样做,也达到了重用代码功能和提高执行效率的效果. 当创建一个类时,您不需要重新 ...

最新文章

  1. Linux那些事儿之我是Sysfs(9)sysfs文件系统模型
  2. 【Java源码分析】Android-SparseArray源码分析
  3. Memcached和Redis
  4. python爬虫架构设置_Python爬虫进阶三之Scrapy框架安装配置
  5. JavaScript HTML DOM 元素(节点)
  6. svn 服务端与客户端安装教程 windows
  7. 32位win10服务器系统,32位win10原版
  8. 视频切割:python将视频文件按秒存储成图片
  9. tensorflow2.0 numpy.ndarray 与tenor直接互转
  10. 【认证】JNCIE-SP备战心得
  11. EasyBoot教程一:制作WIN7原版多重启动盘方法
  12. 第七十三回 玄德进位汉中王  云长攻拔襄阳郡
  13. ssm毕设项目小型超市货物仓储管理系统w8wry(java+VUE+Mybatis+Maven+Mysql+sprnig)
  14. Linux服务器重启后crs,Linux服务器重启后crs_stat -t 命令无法正常使用以及解决思路...
  15. CSS样式-网页响应式设计
  16. Mac Safari 此连接非私人连接
  17. python 文件路径找不到_python路径正确但找不到文件
  18. Promise.all中对于reject的处理
  19. 充电枪cp信号控制板_通过充电枪CP信号控制常电输入的电路的制作方法
  20. not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA

热门文章

  1. vue3.0项目的创建
  2. 香农的“创意思维在编程的应用
  3. sqlserver 高版本数据倒到低版本 不同SQL Server版本间的数据库恢复问题
  4. 【AR】开始使用Vuforia进行Android开发(3)
  5. Nervos 双周报第 7 期:Dev Meetup 正式更名为 Crypto Wednessday 啦!
  6. 10步成为一个优秀的Java开发!
  7. Python基础之六面向对象高级编程
  8. MFC对话框与基础控件个性化
  9. linux 最大文件描述符fd
  10. ppt文件被加密怎么解开,ppt复制打印限制怎么解除?