标准C++06

    科技2024-03-24  96

    一、虚析构 当使用delete释放一个父类指针时(父类引用),不管指向的是父类对象还是子类对象,都只会调用父类的析构。

    当使用多态特性时,如果子类中有需要析构释放的资源,为了避免内存泄漏就需要把父类的析构函数设置为虚函数。

    当父类的析构函数为虚函数时,子类的析构会自动覆盖它而不用比较它们的名字,当通过父类或引用来释放子类对象时会自动调用子类的析构函数。

    二、文件流 C++把对文件的操作封装到了类中。 ifstream 输入文件流 ofstream 输出文件流 fstream 输入/输出文件流

    1、打开文件 使用类的构造函数或open成员函数打开文件,它们的参数一样。 void open( const char *filename, openmode mode ); mode: ios::app 追加输出 ios::ate 当已打开时寻找到EOF ios::binary 以二进制模式打开文件 ios::in 为读取打开文件 ios::out 为写入打开文件, ios::trunc 覆盖存在的文件

    ifstream:默认mode ios::in 为读取打开文件,文件不存在则打开失败 ofstream: 默认mode ios::out 为写入打开文件,文件不存在则创建 ios::trunc 清空存在的文件 fstream: 默认mode ios::in 为读取打开文件 ios::out 为写入打开文件 2、关闭流 close成员函数 与标准C的fclose和系统的close功能一样。

    3、格式化输入输出 可以完全按照cout/cin的使用方式来读写格式化文件。 在读写类或结构时候可以重载输入输出运算符(<</>>)来提高效率,重载方法与cout/cin的一样。 还可以使用一些格式标志来设置输入输出流的格式,通过flags(), setf(), 和 unsetf() 三个函数来控制。 详细格式志请查看帮助手册。

    4、二进制读写 istream &read( char *buffer, streamsize num ); 功能:以二进行格式读取数据 buffer:存储数据的缓冲区 num:想要读取的字节数 注意:返回值并不是成功读取到的字节数,而是流对象的引用,可以通过输入流的成员函数gcount获取成功读取到的字节数。

    ostream &write( const char *buffer, streamsize num ); 功能:以二进制格式写入数据 buffer:待写入的数据的首地址 num:要写入的字节数 注意:返回值不是成功写入的字节数,通过流的good成员函数判断是写入成功。

    5、随机读写 istream &seekg( off_type offset, ios::seekdir origin ); 功能:以偏移称加基础位置设置文件位置指针

    istream &seekg( pos_type position ); 功能:以绝对位置设置文件位置指针

    pos_type tellg(); 功能:获取输入流的文件位置指针

    ostream &seekp( off_type offset, ios::seekdir origin ); ostream &seekp( pos_type position ); pos_type tellp(); 功能:同上

    origin: 基础位置 ios::beg ios::cur ios::end

    练习1:使用C++文件流实现覆盖检查的cp命令。

    三、类型信息 typeid 用于获取数据的类型信息,返回type_info类型临时对象。

    使用前要加头文件typeinfo,type_info对象成员函数name可以获取到基本的缩写,自定义类型的名字及名字的长度,以P开头的是指针类型。

    type_info对象还支持== !=运行符,能分辨出两种个数据是否是同一种类型。

    如果用于判断父子类的指针或引用,它不能准备分辨出实现的对象类型,但如果父类有虚函数,就可以分辨出来。

    四、异常处理 在C++中当代码出现问题时,不能通过返回值和errno反映的,而是随机可以返回一个未知的数据来表示错误。

    抛异常: throw 数据(基本类型|自定义类)。 注意:不能抛出局部对象的指针或引用,因为当异常抛出后函数就执行结束了,函数的栈内存会被释放,如果返回局部对象的指针或引用则返回的是野指针或悬空引用。 最好抛临时对象,而上层代码用const引用捕获。 异常捕获: 注意:如果抛出的异常没有被捕获,程序就会停止。 try{ 可以抛出异常的代码 } catch(const 类型1& 变量名) { 处理异常,如果无法处理可以向上层代码继续抛出异常。 } catch(const 类型2& 变量名) {

    } …

    异常捕获是从上到下匹配,只要合适就算匹配成功,并不是择优匹配。 如果异常类型可能是父子类,那么在捕获时要先子类后父类。

    函数的异常声明: 在声明函数时可以函数的末尾声明此函数可能抛出的异常。 void func(void) throw(类型1,类型2,…);

    1、如果不写异常声明则表示该函数什么类型的异常都可能抛出。 2、如果抛出声明以外的异常类型,则该异常无法捕获,程序肯定会死亡,因此声明异常时要慎重。 3、throw() 表示什么异常都不会抛出

    五、C++标准库异常 C++标准库异常定义了常见的异常,可以直接使用,同时C++标准库中也使用这套异常。 这些异常类都有一个what成员函数,里面记录了异常产生的原因。

    class Error { int errno; char* msg; Error(const Error& that) {} void operator=(const Error& that) {} public: Error(const char* str=“未知类型错误!”,int errno=-1):errno(errno) { msg = new char[strlen(str)+1]; stdrcpy(msg,str); } ~Error(void) { delete[] msg; } const char* msg(void) { return msg; } }

    Processed: 0.012, SQL: 8