8.7 练习

8-1 创建一个类Base,它有一个virtual虚析构函数,同时创建一个派生类Derived,它派生于类Base。创建一个存储Base指针的vector,该指针指向随机生成的Base和Derived对象。使用该vector的内容来填充另外一个包含所有Derived指针的另一个vector。比较typeid()和dynamic_cast的执行时间,看哪一个执行得更快。

8-2 修改本教材第1卷中的C16:AutoCounter.h,使它成为一个有用的调试工具。它将作为那些与追踪有关的各个类的嵌套成员来使用。将AutoCounter修改为一个模板,它将外围类的类名作为模板的参数,并且在所有的出错信息中利用RTTI来打印类名。

8-3 通过使用typeid()打印出模板的准确的名称,用RTTI作为辅助工具进行程序的调试。实例化各种类型的模板,并看看它们的结果是什么。

8-4 通过先将Wind5.cpp复制到一个新位置,修改第1卷第14章中的Instrument的层次结构。现在,在Wind类中新增加一个虚函数clearSpitValve(),并且在继承自Wind的所有派生类中重新定义它。实例化一个存储Instrument指针的vector,并用new操作符创建各种类型的Instrument对象来填充它。现在使用RTTI在这样一个容器中遍历查找类Wind或Wind的派生类的对象。并对这些对象调用clearSpitValve()函数。注意,如果在工具(Instrument)基类中含有一个clearSpitValve()函数,那么将会使该基类发生使人不愉快的混乱。

8-5 修改上一个练习,在该基类中放置一个prepareInstrument()函数,它需要调用适当

的函数(例如,在它适宜的时候调用clearSpitValve())。注意,prepareInstrument()是放置在基类中的一个明智的函数,它的使用剔除了在上一个练习题中对RTTI的需要。

8-6 创建一个含有指针的vector,这些指针指向10个随机Shape对象(例如,至少是若干个Square和Circle)。重写每个具体的类中的draw()成员函数,用于打印输出被画对象的尺寸(任何一个应用的长度或半径)。编写一个main()程序,首先画出容器中所有的Square,并按其长度进行排序,然后再画出所有的Circle,并按其半径进行排序。

8-7 创建一个大的vector,它存储那些指向随机Shape对象的指针。在Shape中编写一个非虚(non-virtual)draw()函数,使用RTTI来确定每个对象的动态类型,并且借助开关(switch)语句执行适当的代码来“画出”对象。然后使用虚函数,“用正确的方法”重新编写Shape的层次结构。比较两种方法的实现代码长度和执行时间。

8-8 创建一个关于Pet类的层次结构,其中包括Dog、Cat和Horse。再创建一个关于Food类的层次结构:其中包括Beef、Fish和Oats。Dog类有一个成员函数eat(),其参数为Beef,同样Cat:eat()将Fish对象作为其参数,而Oats对象则作为参数传递给Horse:eat()。创建这样一个vector,它含有指向随机生成的Pet对象的指针,并且访问每一个Pet,并将正确的Food对象类型传递给对应的eat()函数。

8-9 建立一个名为drawQuad()的全局函数,它使用一个Shape对象的引用作为参数。如果它有4条边(也就是说,它是Square或Rectangle),那么它将调用其含有Shape参数的draw()函数。否则将打印消息“不是一个四边形”。遍历这个包含指向随机生成的Shape对象指针的vector,在遍历时对每个被访问对象调用drawQuad()。在vector中,放置那些指向Square、Rectangle、Circle和Triangle对象的指针。

8-10 根据类名对一个含有随机Shape对象的vector排序。用type_info:before()作为排序的比较函数。