练习7.36:
在类X中,两个数据成员出现的顺序是rem在前,base在后,所以当执行X对象的初始化操作时先初始化rem。如上述代码所示,初始化rem要用到base的值,而此时base尚未被初始化,因此会出现错误。该过程与构造函数初始值列表中谁出现在前面谁出现在后面没有任何关系。
修改的方法很简单,只需要把变量rem和base的次序调换即可,形式是:
struct X
{X(int i,int j):base(i),rem(base%j){}int base,rem;
};
练习7.37:
Sales_data first_item(cin);使用了接受std::istream&参数的构造函数,该对象的成员值依赖于用户的输入。
Sales_data next;使用了Sales_data的默认构造函数,其中string类型的成员bookNo默认初始化为空字符串,其他几个成员使用类内初始值初始化为0。
Sales_data last(“9-999-99999-9”);使用了接受const string&参数的构造函数,其中bookNo使用实参初始化为"9-999-99999-9",其他几个成员使用类内初始值初始化为0。
练习7.37:
满足题意的构造函数如下所示:
Sales_data(std::istream&is = std::cin){is>>*this;}
此时该函数具有了默认构造函数的作用,因此我们原来声明的默认构造函数Sales_data()= default;应该去掉,否则会引起调用的二义性。
练习7.39:
如果我们为构造函数的全部形参都提供了默认实参(包括为只接受一个形参的构造函数提供默认实参),则该构造函数同时具备了默认构造函数的作用。此时即使我们不提供任何实参地创建类的对象,也可以找到可用的构造函数。
然而,如果按照本题的叙述,我们为两个构造函数同样都赋予了默认实参,则这两个构造函数都具有了默认构造函数的作用。一旦我们不提供任何实参地创建类的对象,则编译器无法判断这两个(重载的)构造函数哪个更好,从而出现了二义性错误。
练习7.40:
首先选择(a)Book,一本书通常包含书名、ISBN编号、定价、作者、出版社等信息,因此令其数据成员为:Name、ISBN、Price、Author、Publisher,其中Price是double类型,其他都是string类型。Book的构造函数有三个:一个默认构造函数、一个包含完整书籍信息的构造函数和一个接受用户输入的构造函数。其定义如下:
class Book
{private:string Name,ISBN,Author,Publisher;double Price = 0;public:Book() = default;Book(const string &n,const string &I,double pr,const string &a,const string &p){Name = n;ISBN = I;Price = pr;Author = a;Publisher = p;}Book(std::istream&is){is>>*this;}
};
也可以选择(f)Tree,一棵树通常包含树的名称、存活年份、树高等信息,因此令其数据成员为:Name、Age、Height,其中Name是string类型,Age是unsigned类型,Height是double类型。假如我们不希望由用户输入Tree的信息,则可以去掉接受std::istream&形参的构造函数,只保留默认构造函数和接受全部信息的构造函数。其定义如下:
class Tree
{private:string Name;unsigned Age = 0;double Height = 0;public:Tree() = default;Tree(const string &n,unsigned a,double h):Name(n),Age(a),Height(h);
}