C++ 编写自己的异常类
来源:互联网 发布:淘宝首页钻展费用 编辑:程序博客网 时间:2024/05/16 00:50
1)C++标准库中的异常数目有限,可以在程序中为特定的错误创建更有意义的类名称,而不是使用具有通常名称的异常类,例如runtime_error
2)可以在异常中加入自己的信息,而标准层次结构中的异常只允许设置错误字符串。例如或许想在异常中传递不同的信息。
示例为文件错误定义自己的错误层次结构,从一个泛型类FileError开始:
#pragma once#include<iostream>#include<exception>#include<string>using namespace std;class FileError :public exception{public:FileError(const string& fileIn) :mFile(fileIn) {};virtual const char* what() const noexcept override { return mMgs.c_str(); }const string& getFileName() { return mFile; }protected:void setMessage(const string &message) { mMgs = message; }private:string mFile, mMgs;};
作为一名优秀程序员,应将FileError作为标准异常层次结构的一部分,将其作为exception的子类是恰当的。当编写exception的派生类时,需要重写what()方法,这个方法的原型已经出现过,其返回值作为一个在对象销毁之前一直有效的const char*字符串。在FileError中,这个字符串来自mMsg数据成员,在构造函数中将其设置为“”。FileError的派生类如果想给出不同的消息,就必须用不同的消息设置这个mMsg字符串。
泛型类FileError还包含文件名、访问文件名的公有方法和受保护的设置方法,以便派生类可以设置该消息。
readIntegerFile()中第一种异常情况是无法打开文件。因此,下面编写FileError的派生类FileOpenError:
#pragma once#include"FileError.h"#include<string>#include<iostream>using namespace std;class FileOpenError :public FileError{public:FileOpenError(const std::string& fileNameIn);};
FileOpenError::FileOpenError(const std::string & fileNameIn):FileError(fileNameIn){setMessage("Unable to open" + fileNameIn);}
FileOpenError修改mMsg字符串,令其表示文件打开错误。
readInterFile()的第二种异常情况是无法正确读取文件。对于这一异常,或许应该包含文件中发生错误的行为,以及what()返回的错误信息字符串中的文件名。下面是FileError的派生类FileReadError:
#pragma once#include<iostream>#include<string>#include"FileError.h"#include<sstream>using namespace std;class FileReadError :public FileError{public:FileReadError(const string&fileNameIn, int lineNumIn);int getLineNum() { return mLineNum; }private:int mLineNum;};
FileReadError::FileReadError(const string & fileNameIn, int lineNumIn):FileError(fileNameIn),mLineNum(lineNumIn){ostringstream ostr;ostr << "Error reading " << fileNameIn << " at line " << lineNumIn;setMessage(ostr.str());}
readIntegerFile()函数
正确设置行号,跟踪所读取的行号
#include"stdafx.h"#include<iostream>#include"FileOpenError.h"#include"FileReadError.h"#include<fstream>#include<vector>using namespace std;/**readIntegerFile()函数正确设置行号,跟踪所读取的行号*/void readIntegerFile(const string& fileName, vector<int>&dest){ifstream istr;int temp;string line;int lineNumber = 0;istr.open(fileName);if (istr.fail()){throw FileOpenError(fileName);}while (!istr.eof()){//read one line from the filegetline(istr, line);lineNumber++;//Create a string stream out of the line.istringstream lineStream(line);//Read the integers one by one and add them to the vectorwhile (lineStream >> temp){dest.push_back(temp);}if (!lineStream.eof()){//we did not reach the end of the string stream//this means that some error occurred while reading this line.//throw an exceptionthrow FileReadError(fileName, lineNumber);}}}int main(){vector<int> myInts;const string fileName = "C:/Users/Administrator/Desktop/IntegerFile.txt";try {readIntegerFile(fileName, myInts);}catch (const FileError&e) {cerr << e.what() << endl;return 1;}for (const auto element : myInts){cout << element << " ";}cout << endl;return 0;}
txt文件
输出
编写其对象用作异常的类时,有一个诀窍。当某段代码抛出一个异常时,复制被抛出的值或者对象。也就是说,使用复制构造函数从就对象构造新对象。复制是必须的,因为原始对象在堆栈中的位置较高,可能在异常被捕获之前超出作用域(因此会被销毁,其所占的内存会被回收)。因此,如果编写的类的对象将作为异常抛出,对象必须能复制,这意味着如果动态分配了内存,必须编写析构函数、复制构造函数和赋值运算符。
注意:作为异常抛出的对象至少按值复制一次。
异常可能被复制多次,但只有按值(而不是按引用)捕获异常才会如此。
注意:按引用捕获异常对象可以避免不必要的复制。
- 编写自己的异常类
- C++ 编写自己的异常类
- Android CrashHandler编写自己的异常捕获类
- C++ 编写自己的异常处理
- 在java里面怎么定义异常类用于自己编写的类的异常处理?
- 自己的异常类
- 编写自己的php扩展函数(c)
- 编写自己的C语言头文件
- 编写自己的C语言头文件
- 编写自己的C语言头文件
- C语言编写自己的对数函数
- 编写自己的C++IDE 准备工作
- spring mvc 自己编写异常
- java里自己编写抛出异常的信息
- 编写自己的指针类
- 编写自己的Writeable类
- 定义自己的异常类
- 创建自己的异常类
- mysql
- spring中MessageSource实现国际化i18n
- 网络编程:Reactor与Proactor的概念
- 存储过程-第二课
- android初级学习之ViewPage进一步探索
- C++ 编写自己的异常类
- BroadcastReceiver的两种注册和粘性广播
- Java中解决浮点数精度的问题
- Mac下配置jdk 和maven
- java读hdfs上文件报错:java.lang.IllegalArgumentException: Wrong FS: hdfs:/ expected file:///
- 高性能网络编程4--TCP连接的关闭
- Git的版本和分支管理
- Servlet-JSP
- 欢迎使用CSDN-markdown编辑器