第18章 特殊工具与技术
【140】18.11解释下面的new和delete表达式中发生什么。
struct Exercise{
Exercise();
~Exercise();
};
Exercise*pe=new Exercise[20];
delete[] pe;
答:new表达式动态分配包含20个Exercise对象元素的数组,并调用Exercise类的默认构造函数对数组元素进行初始化。
delete表达式调用Exercise类的析构函数清除由new表达式动态分配的数组中的每个对象,并释放该数组所占用的内存。
【141】18.13给定下面的类层次,其中每个类都定义了public默认构造函数和虚析构函数:
class A{…};
class B:public A{…};
class C:public B{…};
class D:public B,public A{…};
如果有,下面哪些dynamic_cast失败?
a)A *pa=new C;
B *pb=dynamic_cast<B*>(pa);
b)B *pb=new B;
C *pc=dynamic_cast<C*>(pb);
c)A *pa=new D;
B *pb=dynamic_cast<B*>(pa);
答:使用dynamic_cast操作符时,如果运行时实际绑定到引用或指针的对象不是目标类型的对象(或其派生类的对象),则dynamic_cast失败;
b)中dynamic_cast失败。因为目标类型为C,但pb实际指向的不是C类对象,而是一个B类(C的基类)对象。
【142】18.16解释什么时候可以使用dynamic_cast代替虚函数。
答:如果我们需要在派生类中增加新的成员函数(假设为函数f),但又无法取得基类的源代码,因而无法在基类中增加相应的虚函数,这时,可以在派生类中增加非虚成员函数。但这样一来,就无法用基类指针来调用f。如果在程序中需要通过基类指针(如果用该继承层次的某个类中所包含的指向基类对象的指针数据成员p)来调用f,则必须使用dynamic_cast将p转换为指向派生类的指针,才能调用f。也就是说,如果无法为基类增加虚函数,就可以使用dynamic_cast代替虚函数。
【143】18.21普通数据指针或函数指针与数据成员指针或函数成员指针之间的区别是什么?
答:区别在于,指定成员指针(数据成员指针及函数成员指针)的类型时,除了给出成员本身的类型之外,还必须给出所属类的类型(函数成员指针还要指明成员是否为const)。例如:
指向int型数据的普通数据指针的类型为int*,而指向C类的int型数据成员的成员指针类型为int C::*;指向“不带参数并返回int型值的函数”的普通函数指针类型为int(*)(),而指向“C类的不带参数并返回int型值的const成员函数”的函数成员指针的类型为int (C::*)()const;
【144】18.34解释下面这些声明,并指出它们是否合法:
extern “C” int compute(int *,int);
ectern “C” double compute(double *,double);
答:第一个声明指出,compute是一个用C语言编写的函数,该函数接受一个int*类型及一个int类型的形参,返回int型值;
第二个声明指出,compute是一个用C语言编写的函数,该函数接受一个double*类型及一个double类型的形参,返回double型值。
如果这两个声明单独出现,则是合法的;如果二者同时出现,则是不合法的,因为这两个compute函数构成了函数重载,而C语言是不支持函数重载的。