一、纯虚函数和抽象类
1、纯虚函数
在虚函数声明的末尾添加=0,这种没有函数体的函数叫纯虚函数。
virtual 返回值 函数名(参数列表) = 0;
2、抽象类
成员函数中有纯虚函数的类叫抽象类,这种类不能创建对象(不能实体化)。
抽象类只能被继承、被覆盖,由子子类创建对象。
如果继承的抽象类,但没有覆盖纯虚函数,那么子类也变成了抽象类。
3、纯抽象类
所有的成员函数都是纯虚函数,这种类叫做纯抽象类。
这种类一般用于设计接口,这种类的子类被修改后,调用者不需要修改或只需要简单的修改即可继续使用。
注意:有纯虚函数的类就是一种强制的多态。
简历中可以提到的设计模式:
1、命令模式
2、回调模式
3、单例模式
4、工厂模式
5、MVC模式
C++中空的结构、类对象为什么是1字节?
结构、类中可以有成员函数
成员函数需要识别哪个对象调用的它,它需要获取到对象地址。
0字节的结构、类对象,在内存中没有存储位置也就没有了对象地址,这样就无法调用成员函数了。
所以为了让对象能正常调用成员函数,C++规定空的结构、类对象填充一个字节,为对象在内存中占据一个位置,这样对象就有地址来传递给成员函数了。
二、虚函数表
1、虚函数表指针
当一个类中定义了虚函数,那么编译器就会把这些虚函数地址存储一个表格中,然后一个指针来指向该表格,该指针会被包含到类中,因此定义了虚函数的类至少增加4字节。
2、虚函数表
虚函数表中存储的是每个虚函数的地址,当子类继承了分类后,也就继承的虚函数表指针和虚函数表。子类中的成员函数会与虚函数中的每个虚函数进行比较,如果达到覆盖的条件,子类中的函数就会替换虚函数表中的内存,这样该虚函数就被覆盖。
三、虚析构和虚构造
1、构造函数可以是虚函数吗?
如果构造函数是虚函数,那么子类的构造函数必定会覆盖父类的构造函数,当创建子类对象时,会先执行父类的构造函数,但由于实际的调用都是子类,按照多态的则此时就该调用子类的构造,而子类的构造执行前该先调用父类构造,这样就陷入了死循环,所以C++规则构造函数不可以是虚函数。
2、析构函数可以是虚函数吗?
如果析构函数是虚函数,那么子类的析构必定会覆盖父类的析构函数,当通过父类指针释放子类对象时,按照多态规则会调用子类的析构再调用父类的析构,按照正常的子类对象的释放过程也该这么执行,所以析构函数可以是虚函数。
当使用多态时,子类的析构函数有需要释放的资源,通过父类指针释放子类对象时,只会执行父类的析构,那么子类的析构函数就不会执行,可能会导致数据没有保存、资源没有释放,所以这种情况下父类的析构必须是虚函数。
四、I/O流
C++把对文件的操作封装到了类中
ofstream 对文件的写操作
ifstream 对文件的读操作
fstream 对文件的读写操作
五、打开文件
打开文件:类的构造函数open成员函数,他们的参数一样
void open(const char* filename);
void open(const char* filename,openmode mode);
mode含义
ios::app | 添加输出 |
---|---|
ios::ate | 当已打开时寻找到EOF |
ios::binary | 以二进制模式打开文件 |
ios::in | 为读取打开文件,文件不存在则打开失败 |
ios::out | 为写入打开文件 |
ios::trunc | 清空文件内容 |
默认的打开模式:
ifstream ios::in
ofstream ios::out|ios::trunc
fstream ios::in|ios::out
注意:使用 strace ./a.out 追踪打开文件时的标志。
六、文件格式读写
ifstream/ofstream/fstream 的对象使用 << >> 运算符来读写二进制数据。
注意:如果读写的对象是类对象或结构对象,建议重载它们的输入、输出运算符,即可以输入输出数据也可用于文本格式的读写。
七、随机读写
设置输入流的文件位置指针
istream &seekg( off_type offset, ios::seekdir origin );
功能:按照基础位置+偏移的方式设置文件位置指针
origin:
ios::beg 相当于C语言中的SEEK_SET
ios::end 相当于C语言中的EEK_END
ios::cur 相当于C语言中的SEEK_CUR
istream &seekg( pos_type position );
功能:按照绝对位置设置文件位置指针
position:字节数
设置输出流的文件位置指针,参数同步
ostream &seekp( off_type offset, ios::seekdir origin );
ostream &seekp( pos_type position );
pos_type tellg();
功能:获取输入流的文件位置指针
pos_type tellp();
功能:获取输出流的文件位置指针
注意:为什么两套不同的设置,因为有些系统的文件位置指针的两个,分别输入和输出的,但Linux系统只有一个位置指针,因此设置那个都可以。
八、二进制读写
istream &read( char *buffer, streamsize num );
功能:用于二进制格式读数据
buffer:存储数据的缓冲区
num:想要读取的字节数
streamsize gcount();
功能:获取最近一次读取的字节数。
ostream &write( const char *buffer, streamsize num );
功能:用于二进制格式写数据
buffer:待写入的数据的首地址
num:想写入的字节数
bool good();
功能:获取流的上一次操作是否成功,可以用于判断写入数据是否成功,也可以用于打开文件是否成功。
注意:当使用二进制格式读写类对象、结构对象时,对象中不能有指针类型的成员。