11.6 练习
部分练习题的答案可以在本书的电子文档“Annotated Solution Guide for Thinking in C++”中找到,只需支付很少的费用就可以从http://www.BruceEckel.com得到这个电子文档。
11-1 把本章开头的“bird&rock”代码段写为C程序(对数据类型使用structs),并对它编译,试着用C++的编译器对它进行编译,看看会有什么发生?
11-2 把标题为“C++中的引用”的小节的开头部分代码段放入main()中,在输出时增加一些说明,以证明引用就相当于被自动间接引用的指针。
11-3 写一个程序,在其中尝试(1)创建一个引用,在其创建时没有被初始化。(2)在一个引用被初始化后,改变它的指向,使之指向另一个对象。(3)创建一个NULL引用。
11-4 写一个函数,该函数使用指针作为参数,修改指针所指内容,然后用引用返回指针所指的内容。
11-5 创建一个包含若干成员函数的类,再用这个类创建一个对象,该对象被练习4中的参数所指向。让这个指针是const的和这些成员函数是const的,证明仅能在自己的函数内调用const成员函数。让函数参数是引用而不是指针。
11-6 把标题为“指针引用”小节的开头部分的代码段写成为一段程序。
11-7 创建一个函数,使之参数为一个指向指针的指针的引用,要求该函数对其参数进行修改。然后,在main()中,调用这个函数。
11-8 创建一个函数,使其用char&作参数并且修改该参数。在main()函数里,打印一个char变量,使用这个变量做参数,调用我们设计的函数。然后,再次打印此变量以证明它已被改变。请问这影响了程序的可读性吗?
11-9 写一个包含了一个const成员函数和一个非const成员函数的类,再写三个使用刚创建类的对象作为参数的函数:第一个是通过按值传递方式传递参数,第二个是通过引用方式,第三个是通过const引用方式。在这些数的内部,试着调用所创建类的两个成员函数并解释其结果。
11-10 (有点挑战性)写一个简单的函数,该函数使用一个int作为其参数,增加参数的值并返回它。在main()中,调用这个函数。现在观察编译器如何产生汇编代码并且通过汇编描述来追踪,以理解参数是如何被传递和返回的,以及局部变量是如何从栈中索引的。
11-11 写一个函数,该函数使用了char、int、float和double作为其参数。用编译器产生汇编代码并找出在函数调用之前把参数压入栈的指令。
11-12 写一个返回double的函数,产生汇编代码并确定该值是如何被返回的。
11-13 产生PassingBigStructures.cpp的汇编代码,追踪并了解编译器产生代码传送和返回大型结构的方法。
11-14 写一个简单的递归函数,该函数减少参数的值,如果参数变为0则返回0,否则调用它本身。产生这个函数的汇编代码,解释编译器创建汇编代码的过程是如何支持递归的。
11-15 编写代码用来证明当自己没有创建一个拷贝构造函数时,编译器将自动地生成拷贝构造函数。并证明生成的拷贝构造函数将对基本类型执行位拷贝,而对用户定义的类型执行拷贝构造函数。
11-16 创建一个包含拷贝构造函数的类,该类向cout说明它被执行。然后创建一个函数,该函数用按值传递方式传递刚创建类的一个对象。再创建一个函数,此函数产生一个刚创建类的局部对象并通过按值传递方式返回它。调用这些函数以证明当通过按值传递方式传递和返回对象时,实际上是调用了拷贝构造函数。
11-17 创建一个包含double的类,其构造函数通过调用new double来对double进行初始化,并将构造函数的参数中的值赋给结果存储单元。析构函数打印出所指向的值,并把该值设为-1,对存储单元调用delete,然后将指针置0。现在创建一个函数,该函数可通过按值传递方式获取刚创建类的一个对象。在main()中调用这个函数。看看会有什么问题发生。通过创建一个拷贝构造函数来解决这个问题。
11-18 创建一个类,该类中的构造函数就像是一个拷贝构造函数,但它有一个额外的带有默认值的参数。说明这将仍然是作为拷贝构造函数被使用的。
11-19 创建一个带有能显示信息的拷贝构造函数的类。再创建第二个类,该类的成员含有一个由第一个类创建的对象,但不创建拷贝构造函数。验证第二个类中自动生成的拷贝构造函数将调用第一个类的拷贝构造函数。
11-20 创建一个非常简单的类和一个函数,该函数通过按值传递方式返回所创建类的一个对象。再创建第二个函数,它以一个所创建类的对象的引用为参数。作为第二个函数的参数,调用第一个函数,并说明第二个函数必须在它的参数中使用const引用。
11-21 创建一个没有拷贝构造函数的简单的类和一个简单的函数,此函数通过按值传递方式接收的参数是所创建类的一个对象。现在通过(仅)对拷贝构造函数增加一个私有声明来改变你的类。请解释当创建的函数被编译时将会发生什么。
11-22 本练习会创建一个拷贝构造函数的替代物。创建一个类X并声明(但不定义)一个私有类型拷贝构造函数。创建一个公有函数clone()以作为一个const成员函数,该成员函数返回一个用new创建的对象的拷贝。现在写一个函数,使用const X&作参数并且复制了一个能被修改的局部拷贝。这种方法的缺点是当你这样做时,必须确保显式地销毁(使用delete)被复制的对象。
11-23 解释第7章中Mem.cpp和MemTest.cpp的错误,并解决其问题。
11-24 创建一个类,它含有一个double类型数据成员和一个打印double的print()函数。在main()中,再分别创建指向所创建类中的数据成员和函数的成员的指针。创建类的一个对象和指向该对象的一个指针,通过指向成员的指针,再使用对象和指向对象的指针,来操纵类的这两种成员。
11-25 创建包含一个整型数组的类。能否通过使用指向成员的指针对这个数组进行索引?
11-26 通过增加一个重载的成员函数f()(你可以决定重载的参数表),修改PmemFunDefinition.cpp。再创建一个成员指针,使它指向f()的重载版本,然后通过这个指针调用此函数。在这种情况下,重载的结果会如何发生?
11-27 根据第3章的FunctionTable.cpp,创建包含了一组函数指针的vector向量的类,用add()和remove()成员函数来增加和减少函数指针。再增加一个run()函数,该函数可在vector中移动,并可调用所有的函数。
11-28 修改练习27,使它能够用指向成员函数的指针来完成上述工作。