C++ IO流 异常处理

一、虚函数表

什么是虚函数表,在C++的类中,一旦成员函数中有虚函数,这个类中就会多一个虚函数表指针,这个指针指向一个虚函数表,表中记录了这个类中所有的虚函数,当这个类被继承,它的子类中也会有一个虚函数表(不管子类中有没有虚函数),如果子类的成员函数中有函数签名与父类的虚函数一样的就会用子类中的函数替换它在虚函数中的位置,这样就达到了覆盖的效果

当通过类指针或引用调用函数时,会根据对象中实际的虚函数表记录来调用函数,这样就达到了多态的效果	

二、虚析构

当使用 delete 释放父类指针时,不管实际指向的对象是子类还是父类都会调用父类的析构函数(多态肯定会出现的问题)

如果子类的析构函数有需要负责释放的内存,就会造成内存泄露

为了解决这个问题,可以把父类的析构函数设置为虚函数,析构函数进行覆盖时不会比较函数名。
当父类的析构为虚函数时,通过父类指针或引用释放子类对象时,会自动调用子类的析构函数,子类的析构函数执行完成后也会调用父类的析构函数。

注意:析构函数可以是虚函数,但构造函数不可以。

三、强制类型转换

注意:C++中为了兼容C原因,(目标类型)源类型 依然可以使用,但C语言中的强制类型转换安全性差,因此建议使用C++中的强制类型转换
注意:C++之父认为如果代码设计的完善,根本不需要用到强制类型转换,而C++的强制类型转换之所以设计的很复杂,是为了让程序员多关注代码本身的设计,尽量少使用。

C++中的强制类型转换保证没有很大的安全隐患

static_cast <目标类型>(源类型)
	编译器会对源类型和目标类型做兼容性检查
dynamic_cast<目标类型>(源类型)
	编译器会会对源类型和目标类是否同为指针或引用,并且存在多态型的继承关系
const_cast<目标类型>(源类型)
	编译器会会对源类型和目标类是否同为指针或引用,除了常属性外其他必须完全相同否则报错
reinterpret_cast<目标类型>(源类型)
	编译器会会对源类型和目标类是否同为指针和整数进行检查

静态编译:
	指针或引用的目标是确定的,在编译时期就经过了所有类型检查、函数调用
动态编译:
	指针或引用的目标是确定(多态),只有函数调用时候才确定,具体是哪个子类。

四、I/O流

ios::in		以读权限打开文件,不存在则失败,存在不清空
ios::out	以写权限打开文件,不存在则创建,存在则清空
ios::app 	打开文件用于追加,不存在则创建,存在不清空
ios::binary	以二进制模式进行读写
ios::ate	打开时定位到文件末尾
ios::trunc	打开文件后清空

fstream/ifstream/ofstream类用于进行文件操作
	构造函数或成员函数 open 用于打开文件
	good成员函数检查流是否可用
	eof成员函数用于输入流是否结束
	
	>>操作符用于从文件中读取数据到变量
	<<操作符用于输入数据到文件
	
	IO流有一系列格式化控制函数,类似于左对齐、右对齐、宽度、填充、小数点位数
	二进制读写:read/write
		read(char_type *__s,streamsize __n);
		gcount成员函数可以获取上次流的二进制读写操作的字节数
		
		write(char_type *__s,streamsize __n);
		good成员函数可以获取到写t操作是否成功
	随机读写:seekp (off_type,ios_base::seekdir)
		功能:设置文件的位置指针
		off_type:偏移值
			正值向右,负值向左
		seekdir:基础位置
			ios::beg	文件开头
			ios::cur	文件当前位置
			ios::end	文件末尾
			
	获取文件
	该成员函数返回当前文件流的位置指针(字节数)
	也可以借助此函数获取文件的大小
	
	fs.tellp() 返回字节数
	
	练习:使用C++标准IO实现带覆盖监测的cp命令

五、类型信息 typeid

用于获取数据的类型信息
name成员函数,可以获取类型的名字,内建类型名字使用缩写
同时还支持 == != 用来比较是否是同一种类型

如果用于判断父子类的指针或引用,它不能准确判断出实际的对象类型
但可以判断出具有多态继承的关系的父子类的指针或引用,它的实际类对象。

sudo find / -name filename
sudo find / | grep "std"
grep 'Base' * 当前目录查找文件中包含的字符
grep -r 'Base' * 当前目录查找文件中包含的字符,包括所有子级目录
grep -r 'Base' * dir 指定目录下查找文件中包含字符,包括所有子级目录

六、异常处理

抛异常
	throw 数据
	抛异常对象
	抛基本类型
	注意:不能抛出局部对象的指针和引用
	注意:如果异常没有被捕获,程序就会停止
捕获异常
	try{
		可以抛出异常的代码
	}
	catch(类型 变量名) // 根据数据类型进行捕获
	{
		处理异常,如果无法处理可以继续抛出异常
	}
	注意:捕获异常的顺序是自上而下的,而不是精准的匹配,针对子类异常捕获时要放在父类的前面
	
	函数的异常声明:
		返回值类型 函数名(参数列表)异常声明
		注意:如果不写异常声明表示什么类型的异常都可能抛出
		注意:如果写了异常声明表示只抛出某些类型的异常,一旦超出异常声明的范围,程序会直接结束,无法捕获
		注意:threw()
设计异常类:
class Error
{
	int errno;
	char errmsg[255];
public:
	Error(int errno = -1,const char* msg = "未知错误")
	{
		this->errno = errno;
		strcpy(errmsg,msg);
	}
	int getError(void);
	{
		return errno;
	}
	const char* getErrmsg(void)
	{
		return errmsg;
	} 
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章