本文答案,部分参考于C++ Primer 习题集
前面章节的习题答案
配套的学习资料
https://www.jianguoyun.com/p/DTK5uJgQldv8CBjKv80D
19.1
#include<cstdlib>
#include<new>
using namespace std;
void *operator new (size_t size){
if(void *mem=malloc(size)) return mem;
else throw bad_alloc();
}
//编译时必须指定C++11,否则noexcept会导致编译错误.
void operator delete(void *mem) noexcept{
free(mem);
}
19.2
T *newelements=alloc.allocate(newcapacity); //原
T *newelements=static_cast<T *>(operator new [] (newcapacity *sizeof(T))); //后
alloc.deallocate(elements,end-elements);
operator delete[](elements);
19.3
使用dynamic_cast操作符时,如果运行时绑定到引用或指针的对象不是目标类型的对象(或其公有派生类的对象),则dynamic_cast失败.
dynamic_cast转换失败,因为目标类型是C,但pb实际指向的不是C类对象,而是一个B类(C的基类)对象.
c失败的原因是A是D的一个二义基类
要使用RTTI,需要在编译器中设置相应编译选项,
19.4
19.5
如果我们需要在派生类中增加新的成员函数f,但又无法取得基类的源代码,因而无法在基类中增加相应的虚函数,这时,可以在派生类中增加非虚成员函数,但这样一来,就无法用基类指针调用函数f,如果在程序中需要通过基类指针(如使用该继承层次的某个类中所包含的指向基类对象的指针数据成员p)来调用f,则必须使用dynamic_cast将p转换为只想派生类的指针,才能调用f,也就是说,如果无法为基类增加虚函数,就可以使用dynamic_cast代替虚函数.
19.6
19.7
19.8
假设指针qb1和qb2的类型为Query_base*,则判断两个Query_base指向是否指向相同的typeid表达式如下:
typeid(*qb1)==typeid(*qb2);
判断该类型是否为AndQuery的typeid表达式如下:
typeid(*qb1)==typeid(AndQuery);
19.9
19.10
typeid操作符的结果是type_info类对象,type_info类的成员函数name返回一个C风格字符串,代表type_info对象所表示的类型的名字,返回的C风格字符串的格式和值根据编译器而定.
class A*
class A*
class A
19.11
区别在于,指定指向数据成员的指针的类型时,除了给出成员本身的类型之外,还必须给出所属类的类型,例如:指向int型数据的普通数据指针的类型为int*,而指向C类的int型数据成员的成员指针的类型为int C:😗
19.12
19.13
Sales_data类的bookNo成员是一个数据成员,其类型为std::string,可以表示Sales_data类的bookNo成员的成员指针的类型为:
std::string Sales_data::*
19.14
合法
19.15
区别在于:指定指向成员函数的指针类型时,除了给出成员本身的类型之外,还必须给出成员函数所属类的类型并指明成员函数是否为const,例如:指向int型数据的普通数据指针的类型为int*,指向"不带参数返回int型值的函数"的普通函数指针的类型为
int(*)(),
而指向 “C类的不带参数并返回int型值的const成员函数"的函数成员指针的类型为int(C:😗)const
19.16
Sales_data的avg_price成员是一个函数成员,其原型为:
double avg_price() const;
19.17
在给出Screen类版本中,成员函数有4个可区分类型,2个get函数为2个不同类型,home等5个光标移动函数为一个类型,move函数为一个类型,因此可以定义4个类型别名Pmf1,Pmf2,Pmf3,Pmf4:
typedef char(Screen::*Pmf1)()const;
typedef char(Screen::*Pmf2)(Screen::index,Screen::index) cosnt;
typedef Screen &(Screen::*Pmf3)();
typedef Screen &(Screen::*Pmf54)(Screen::Directions);
19.18
首先用mem_fn将string的empty成员函数转换为可调用对象,将它作为第三个参数传递给count_if即可实现统计所有空string(令empry返回真值)的数量.
count_empty_string(vector<string>&vs){
auto f=men_fn(&string::empty);
return coutn_if(vs.begin(),vs.end(),f);
}
19.19
19.20
19.21
19.22
19.23
19.24
因为在移动赋值运算符上添加了检测机制,当一个对象自己给自己赋值时,会先检测,避免不必要或者是灾难性的后果
19.25
19.26
第一个声明指出:compute是一个用C语言编写的函数,该函数接受一个int*类型及第二个形参,返回int型值.
第二个声明指出:compute 是一个用C语言编写的函数,该函数接受一个double*类型及一个double类型的形参,返回double型值.
如果这两个声明单独出现,则是合法的;如果两者同时出现,则是不合法的,因为则两个compute函数构成了函数重载,而C语言是不支持函数重载的.