8.7 练习

部分练习题的答案可以在本书的电子文档“Annotated Solution Guide for Thinking in C++”中找到,只需支付很少的费用就可以从http://www.BruceEckel.com得到这个电子文档。

8-1 创建三个const int值,把它们加到一起得到一个值用来在一个数组定义中决定该数组的大小。在C中编译一遍相同的代码,看看会出现什么情况(通过使用命令行标记,可以将C++编译器改作为C编译器运行)。

8-2 自行证实C编译器和C++编译器对于const的处理是不同的。创建一个全局的const并将它用在一个全局的常量表达式中;然后分别用C和C++编译它。

8-3 为所有的内建类型创建const定义及其变量。和其他的const一起在表达式中使用定义新的const。并确保编译正确无误。

8-4 在一个头文件中创建一个const定义,包含这个头文件在两个.cpp文件中,然后编译这些文件并连接它们。要保证正确无误,再在C环境下试一遍。

8-5 创建一个const,当程序运行时,通过读时间决定它的值(必须使用标准的头文件<ctime>),然后在这个程序中读时间的第二个值,并赋给const,看看会有什么结果。

8-6 创建一个char的const数组,然后尝试修改string数组中的某一个值。

8-7 在一个文件中创建一个extern const声明,该文件的main()函数打印extern const的值,在另外一个文件中定义extern const,然后编译和连接这两个文件。

8-8 使用不同的声明形式创建两个指向const long的指针,一个指针指向一个long数组。演示能让指针增加和减少,但不能改变它所指向的值。

8-9 写一个指向double类型的const指针,让它指向double数组。显示能改变指针指向的内容,但不能增加或减小指针。

8-10 写一个指向const对象的const指针。显示只能读指针所指向的值,但不能改变该指针或它所指向的值。

8-11 删除PointerAssignment.cpp文件中代码的错误行前的注释,看看编译器会产生什么样的错误。

8-12 创建一个字符数组字面值和一个指向该数组开始点的指针,使用这个指针修改数组中的元素,看看编译器是否会报告出错,应当出错吗?如果没有,为什么会认为出错?

8-13 创建一个函数,它带有一个以const值传递的参数,然后在函数体中试图改变该参数。

8-14 创建一个函数,它带有一个按值传递的float参数。在函数体中,把const float&绑定到函数的参数上,并且从那时起仅仅使用引用,以确保不改变参数。

8-15 修改ConstReturnValues.cpp文件,每次删除错误行前的注释,看看编译器会产生什么错误信息。

8-16 修改ConstPointer.cpp文件,每次删除错误行前的注释,看看编译器会产生什么错误信息。

8-17 制造文件ConstPointer.cpp的新版,名为ConstReference.cpp,其中把前者使用的指针用引用代替(也许需要用到第11章中的知识)。

8-18 修改ConstTemporary.cpp文件,删除错误行前的注释,看看编译器会产生什么错误信息。

8-19 创建一个包含const和非const float成员的类。用构造函数的初始化列表进行初始化。

8-20 创建类MyString,它包含一个string成员、一个初始化该string成员的构造函数以及print()函数。修改StringStack.cpp文件,以便让容器保存MyString对象,main()函数打印它们。

8-21 创建包含一个const成员和一个枚举成员的类。在构造函数的初始化列表中初始化const成员,无标记的枚举成员用来决定数组大小。

8-22 在ConstMember.cpp文件中,删除成员函数定义前的const限定符,但是让const限定符出现在声明中,看看会得到何种类型的编译器错误信息。

8-23 创建一个类,它有一个const和非const成员函数。再创建该类的cosnt和非const对象,用不同类型的对象调用不同类型的成员函数。

8-24 创建一个类,它有一个const和非const成员函数。尝试从const成员函数中调用非const成员函数,看看会得到何种类型的编译器错误消息。

8-25 在Mutable.cpp文件中,删除错误行前的注释,看看编译器会产生什么错误信息。

8-26 修改Quoter.cpp文件的函数quote(),使它变为const成员函数和lastquote mutable。

8-27 创建一个类,它有一个volatile数据成员,创建一个volatile和一个非volatile成员函数用于修改volatile数据成员。看看编译器会出现什么情况。创建该类的volatile和非volatile对象,尝试调用volatlie和非volatile成员函数,看看哪一个调用会成功,哪一个调用不成功,以及编译器会产生什么样的错误信息。

8-28 创建一个具有成员函数fly()的名为bird的类和一个不含fly()的名为rock的类。建立一个rock对象,取它的地址,并把它赋给一个void。再取这个void,把它赋给一个bird(必须使用类型转换),通过指针调用函数fly()。为什么C语言允许通过void(而不是类型转换)公开地赋值?这是C语言中的一个“缺陷”吗?不能把它推广到C++中吗?