第 1 章习题答案
名词解释
抽象:抽象(Abstract)就是忽略事物中与当前目标无关的非本质特征,而强调与当前目标有关的本质特征,从而找出事物的共性,并把具有共性的事物划为一类。面向对象方法中的抽象,是指对具体问题(对象)进行概括,抽出一类对象的公共性质并加以描述的过程。
封装:面向对象方法中的封装就是把将抽象出来的对象的属性和行为结合成一个独立的单位,并尽可能隐蔽对象的内部细节。
消息:消息是面向对象程序设计用来描述对象之间通信的机制。一个消息就是一个对象要求另一个对象实施某种操作的一个请求。
填空题
(1) 面向过程的结构化程序设计方法面向对象程序设计方法
(2) 顺序选择循环
(3) 程序=数据结构+算法程序=对象+消息
(4) 过程类
(5) 抽象性封装性继承性多态性选择题
(1) B (2) C (3) D (4) C (5) D (6) A (7) A (8) B C (9) A D
判断题(1) t (2) f (3) f (4)f (5) t (6) f (7) f (8) t
简答题
(1) 结构化程序设计方法着眼于系统要实现的功能,从系统的输入和输出出发,分析系统要做哪些事情,进而考虑如何做这些事情,自顶向下地对系统的功能进行分解,来建立系统的功能结构和相应的程序模块结构,有效地将一个较复杂的程序系统设计任务分解成许多易于控制和处理的子任务,便于开发和维护。随着程序规模与复杂性的增长,这种面向过程的结构化程序设计方法存在明显的不足之处。首先是数据安全性问题,由于数据被每个模块所共用,因此是不安全的,一旦出错,很难查明原因。其次是可维护性及可重用性差,它把数据结构和算法分离为相互独立的实体,一旦数据结构需要改变时,常常要涉及整个程序,修改工作量极大并容易产生新的错误。每一种相对于老问题的新方法都要带来额外的开销。另外,图形用户界面的应用程序,很难用过程来描述和实现,开发和维护也都很困难。
(2) 面向对象的程序设计方法中,将程序设计为一组相互协作的对象(Object)而不是一组相互协作的函数。在程序中,属性用数据表示,用来描述对象静态特征;行为用程序代码实现,用来描述对象动态特征。可见,在面向对象的程序设计方法中,对象是数据结构和算法的封装体。对象之间存在各种联系,它们之间通过消息进行通信。程序可表示为:程序=对象+消息在面向对象程序设计中,它着重于类的设计。类正是面向对象语言的基本程序模块,通过类的设计,来完成实体的建模任务。类通过一个简单的外部接口,与外界发生关系。一个类中的操作不会处理到另一个类中的数据,这样程序模块的独立性、数据的安全性就有了良好的保障。程序的执行取决于事件发生的顺序,由顺序产生的消息来驱动程序的执行。不必预先确定消息产生的顺序,更符合客观世界的实际。并且面向对象程序设计方法提供了软件重用、解决大问题和复杂问题的有效途径,具有抽象性、封装性、继承性和多态性等特点。
(3) 结构化程序设计方法中,把数据结构和算法分离为相互独立的实体。在面向对象程序设计中,数据结构和算法是封装在一起,结合成一个独立的单位,即对象,并尽可能隐蔽对象的内部细节。对象的私有属性只能由这个对象的行为来读取和修改,与外部的联系通过公有行为充当外部接口。
第 2 章习题答案
名词解释
引用:所谓引用,就是给对象起一个别名,使用该别名可以存取该对象。换句话说,是使新对象和原对象共用一个地址。
内联函数:内联函数是使用inline 关键字声明一个函数。
重载函数:重载函数通常用来对具有相似行为而数据类型不同的操作提供—个通用的名称。
填空题
(1) 函数类
(2) // /*……*/
(3) iostream
(4) cin >>
(5) cout<<
(6) 地址值类型值
(7)& 对象
(8) 声明
(9) 值传递引用传递
(10) inline
(11) new delete
(12) x= 10, y=10 x= 100 , y=100
选择题(1) A (2)C (3) C (4) A (5) D (6) D (7) D (8) B C (9) A (10) D
判断题(1) t (2) f (3) f (4)t (5) t (6) t (7) t (8) t
简答题
(1) 名字空间用来防止命名的冲突。
(2) 除了独立引用外,在C++程序中,引用的主要用途是用作函数参数和函数的返回值。
(3) 在值传递机制中,作为实参的表达式的值被复制到由对应的形参名所标识的一个对象中,作为形参的初始值。函数体对形参的访问、修改都是在这个标识对象上操作,与实参无关,即数据的传递是单向的。使用引用作函数的形参时,调用函数的实参要用变量名。实参传递给形参,相当于在被调用函数中使用了实参的别名。于是,在被调用函数中对形参的操作,实质是对实参的直接操作,即数据的传递是双向的。
(4) 内联函数是使用inline 关键字声明一个函数。在程序编译时,编译系统将程序中出现内联函数调用的地方用函数体进行替换,进而减少了时间开销。使用内联函数应注意:递归
函数不能定义为内联函数。内联函数一般适合于不含有switch 和while 等复杂的结构且只有1~5 条语句的小函数,否则编译系统将该函数视为普通函数。内联函数只能先定义后使用,否则编译系统也将该函数视为普通函数。对内联函数也不能进行异常接口声明。
(5) 不必一致。所有的参数是根据位置和类型而不是名字来区分的。
(6) 编译系统将根据函数参数的类型和个数来判断使用哪一个函数。
程序分析题(写出程序的输出结果,并分析结果)
程序的输出结果:num=60 ref=100
程序设计题//xiti2_1.cpp
#include
#include
using namespace std;
int main()
{ float x,y; cout<<"please input 2 floats to x,y:"<>x>>y; float z=pow(x,y);
cout<<"pow("<<<""<<<")="< 类实际上由一个类定义的类型称为类类型,程序员可以使用这个新类型在程序中声明新的变量,具有类类型的变量称为对象。创建对象时,类被用作样板,对象称为类的实例。 (2) 定义类一般形式为:class 类名{ public:< 公有数据和函数> protected:< 保护数据和函数> private:< 私有数据和函数> }; 访问权限共有三种:分别是公有(public)、保护(protected)和私有(private)的。 (3) 指创建类的对象。 (4) this 指针是C++为成员函数提供的一个隐含对象指针,它不能被显式声明。this 指针是一个局部量,局部于某个对象。不同的对象调用同一个成员函数时,编译器根据this 指针来确定应该引用哪一个对象的数据成员。 (5) 拷贝构造函数是一种特殊的构造函数,它的作用是用一个已经存在的对象去初始化另一个对象时。为了保证所引用的对象不被修改,通常把引用参数声明为const 参数。在以下 3 种情况下,拷贝构造函数都会被自动调用:①当用类的一个对象去初始化该类的另一个对象时。 ②当函数的形参是类的对象,进行形参和实参结合时。③当函数的返回值是类的对象,函数执行完成返回调用者时。 程序分析题(1) Init defa Init defa Init 15 (2) Exit main dst 5 (3) Default constructor of Part Constructor of Part,3 Default constructor of Part Constructor of Whole Destructor of Whole Destructor of Part,0 Destructor of Part,3 Destructor of Part,0 (4) 30 程序设计题 (1) //xiti3_1.cpp #include< iostream > using namespace std; class Circle { public: Circle(float r){ radius = r; } ~ Circle( ) {} float area() { return 3.14 * radius * radius; } private: float radius; }; int main( ) { float r; cout<< “请输入圆的半径:”; cin >> r; Circle p(r); cout<< “半径为”<< r<< “的圆的面积为:”<< p. area ()<< endl; return 0; } (2) //xiti3_2.cpp #include using namespace std; class Book { public: Book(int w); static int sumnum; static int getsum(){return sumnum;} private: int num; }; Book: :Book(int w) { num=w; sumnum-=w; } int Book::sumnum=120; int main() { Book b1(20); Book b2(70); cout<< 成员。在类外部,派生类的对象无法访问基类的所有成员。当类的继承方式为保护继承时,在派生类中,基类的公有成员和保护成员作为派生类的保护成员,派生类的成员函数可以直接访问它们,而派生类的成员函数无法直接访问基类的私有成员。在类外部,派生类的对象无法访问基类的所有成员。 (4) 首先基类构造函数被调用,子对象所在类构造函数次之,最后执行派生类构造函数。 (5) 若派生类有构造函数而基类没有,当创建派生类的对象时,派生类的相应构造函数被自动调用。若派生类没有构造函数而基类有,则基类必须拥有缺省构造函数。只有这样,当创建派生类的对象时,才能自动执行基类的默认构造函数。若派生类有构造函数,且基类有缺省构造函数,则创建派生类的对象时,基类的缺省构造函数会自动执行,除非当前被调用的派生类构造函数在其初始化段中显式地调用了基类的有参构造函数。若派生类和基类都有构造函数,但基类没有缺省构造函数,则派生类的每一个构造函数必须在其初始化列表中显式地调用基类的某个构造函数。只有这样,当创建派生类的对象时,基类的构造函数才能获得执行机会。 程序分析题(11,12) (26,29) 15,16 (26,29) 程序设计题 //xiti4_1.cpp #include class Point //定义基类{ protected: int x,y; public: Point(int myx,int myy){x=myx;y=myy;} void displayxy() { cout<<"The postion of point:"; cout<<"("< {l=myl;w=myw;} void displaylw() { cout<<"The length and width of rectangle:"; cout< myy){x=myx;y=myy;} void displayxy() { cout<<"the position of center:"; cout<<"("< void displayr(){cout<<"the radius of circle:"< 消息却产生不同的函数调用,="" 通过虚函数来实现;="" 多态性有两种表现形式:一种是不同的对象在收到相同的消息时,产生不同的动作,这主要="" 态。C++支持两种多态性,编译时的多态性和运行时的多态性。="" 即是指同一个函数的多种形="" 多态性就是同一符号或名字在不同情况下具有不同解释的现象,="" 抽象类="" 0="" 静态="" 使用了不恰当的虚函数="" 覆盖="" 动态="" 编译时的多态性,运行时的多态性。="" 5="" v.displayr();="" cout<< (2) 重载函数只要求函数有相同的函数名,并且重载函数是在相同作用域中定义的名字相同的不同函数。而虚函数不仅要求函数名相同,而且要求函数的签名、返回类型也相同。也就是 说函数原型必须完全相同,而且虚函数特性必定是体现在基类和派生类的类层次结构中。重载函数可以是成员函数或友员函数,而虚函数只能是非静态成员函数。构造函数可以重载,析构函数不能重载。正好相反,构造函数不能定义为虚函数,析构函数能定义为虚函数。重载函数的调用是以所传递参数序列的差别作为调用不同函数的依据而虚函数是根据对象的不同去调用不同类的虚函数。重载函数在编译时表现出多态性,是静态联编;而虚函数则在运行时表现出多态性是动态联编,动态联编是C++的精髓。 (3) 包含有纯虚函数的类称为抽象类。抽象类用来描述一组子类的共同的操作接口,它用作基类,而接口的完成实现由派生类提供。抽象类的派生类不一定要给出纯虚函数的实现。如果没有在派生类中给出纯虚函数的实现中,则需仍将它说明为纯虚函数,否则编译器将给出错误信息。说明了纯虚函数的派生类仍是抽象类。 (4) 能声明虚析构函数。如果一个类的析构函数是虚函数,那么,由它派生而来的所有子类的析构函数也是虚函数。delete 运算符和析构函数一起工作,当使用delete 删除一个对象时,delete 隐含着对析构函数的一次调用,如果析构函数为虚函数,则这个调用采用动态联编。这样保证了基类类型的指针能够调用适当的析构函数针对不同的对象进行清理工作。 程序设计题(2) //xt5_2.cpp // 应用实例 #include #include using namespace std; class Shape { public: Shape(); void show(); virtual ~Shape(){} virtual float area()=0; virtual string shapename()=0; protected: string name; static int count; }; Shape::Shape() { cout<<"请输入"; count=count+1; } void Shape::show() { cout<<"第"< 为?<myw>>myh; w=myw; h=myh; } class Rectangle:public Shape { public: Rectangle(); ~Rectangle(){cout<<"Rectangle destructor is called"<<="" l,="" l*w;}=""> }; Rectangle::Rectangle() { float myl,float myw; cout<<"矩形的长和宽:"; cin >>myl>>myw; l=myl;w=myw; } class Circle:public Shape { protected: float radius; public: Circle(); ~Circle(){cout<<"Circle destructor is called"<<>r; radius=r;} int Shape::count=0; int main() { Shape *s[4]; s[0]=new Triangle(); s[0]->show(); s[1]=new Rectangle(); s[1]->show(); s[2]=new Circle(); s[2]->show(); s[3]=new Circle(); s[3]->show(); float sum=total(s,4); cout<<"上述图形的面积和为:"; cout< (1) 函数 (2) 非静态成员函数友员函数 (3) 少 (4) 对象的引用 (5) 整型 (6) 多 选择题(1)B (2)C (3) A (4)C 判断题(1)t (2) f (3) t (4) f 操作题(2) 提示:需要声明如下形式带默认值的构造函数:fraction(int x=0,int y=1); 需要定义一个成员函数去优化分数,如化简、不让负号在分母处等。参考代码如下:void fraction::optimization() { int gcd,min,max; if(fenzi==0) {//如分子为0,则分母为1 后,返回fenmu=1; return; } gcd=(abs(fenzi)>abs(fenmu)?abs(fenmu):abs(fenzi)); if(gcd==0) return; //以下用辗转相除法求最大公约数if(abs(fenzi)>abs(fenmu)) { max=fenzi; min=fenmu; } else { min=fenzi; max=fenmu; } do { gcd=max%min; max=min; min=gcd; }while(gcd!=0); fenzi/=max; fenmu/=max; if(fenzi<0&&fenmu<0) { fenzi=-fenzi; fenmu=-fenmu; } else if(fenzi<0&&fenmu>0) { fenzi=fenzi; fenmu=fenmu; } else if(fenzi>0&&fenmu>0) { fenzi=fenzi; fenmu=fenmu; } if(fenzi>0&&fenmu<0) { fenzi=-fenzi; fenmu=-fenmu; } } (3) 提示:分数化简后再比较。//第六章例题:6.3 #include using namespace std; class complex { public: complex(double r=0.0,double i=0.0); complex operator +(complex c); complex operator -(complex c); void display(); private: double real,imag; }; complex complex::(double ) 第7 章习题答案 名词解释题 函数模板:一个带类属参数的函数。 类模板:一个带类属参数的类 模板函数:通过参数实例化可以再构造出具体的函数。 模板类:通过参数实例化可以再构造出具体的类。 填空题 (1) 函数模板类模板 (2) template (3) class typename (4) 类属参数类似 (5) 没有 (6) 类模板 (7) 顺序容器关联容器 (8) 输入迭代器输出迭代器前向迭代器双向迭代器 选择题 (1) A (2) A (3) AB (4) C (5) ABD 判断题(1) t (2) f (3) t (4) f (5) f 程序设计题(1)(xt7_1.cpp)(2)(xt7_2.cpp) 第8 章习题答案填空题(1) 流流类(2) 标准输入(3) cin cout cerr clog 随机访问迭代器 (4) fstream.h (5) ios 类的成员函数使用控制符(6) 顺序文件随机读写文件(7) 输入文件流输出文件流输入/输出文件流(8) 一个指定的文件(9) 0 (10) read write 选择题(1)B (2) A (3) BCD (4)C (5) A (6) C (7) AB (8) AD BC (9)D (10) B (11)A (12) BC (13) C (14)C (15)BCD (16) C 判断题(1) f (2) t (3)t (4)f (5) t (6) f 简答题(1) 从流类库的基本结构可以看到,ios 类是istream 类和ostream 类的基类,从ios 类公有派生istream 和ostream 两个类,而iostream 类通过多重继承istream 类和ostream 类而产生的。如果不将ios 类作为其派生类的虚基类,可能会产生二义性。 (2) 在文本文件中,每个字节存放一个ASCII 代码表示一个字符,文本文件的优点是可直接按字符形式输出,供人们阅读。二进制文件则是把数据的内部存储形式原样存放到文件中,这种文件的优点是与数据在内存中的存储形式保持一致,因此存储效率高,无须进行存储形 式的转换,但不能直接按字符形式输出。对于那些保存中间运算结果的临时工作文件,使用二进制形式较为合理。 程序分析题输出结果:Hello,students! Welcome you to oop! 程序设计题 (1)参考程序:#include class Fraction { public: Fraction(int x=0,int y=1); friend ostream& operator<<(ostream&,Fraction); private: int den; //分子int num; //分母}; Fraction::Fraction(int x,int y) { den=x; num=y; } ostream& operator<<(ostream& os,Fraction fr) { os< main()="" paginaadss?="" cout<< 第3章面向对象程序设计基础 第3章面向对象程序设计基础 【1】什么是Java程序使用的类?什么是类库? 答:类是将一类事物的特性描述出来,然后如果用这个类来定义对象,则该对象就拥有了这个类所描述的所有特性。 在Java系统中,系统定义好的类根据实现的功能不同,可以划分成不同的集合,每个集合称为一个包,所有包合称为类库。 【2】如何定义方法?在面向对象程序设计中方法有什么作用? 答:方法的定义由两部分组成:方法声明和方法体。 方法的声明如下: 返回值类型方法名(参数类型形式参数1,参数类型形式参数2…){ 程序代码; 返回值; } 在面向对象程序设计中,方法的作用是完成对类和对象属性操作。 【3】简述构造方法的功能和特点。下面的程序片段是某学生为student类编写的构造方法,请指出其中的错误。 void Student(int no,String name) { studentNo=no; studentName=name; return no; } 答:构造方法的功能是:构造方法是一个特殊的方法,主要用于初始化新创建的对象; 特点:构造方法的方法名要求与类名相同,用户不能直接调用,只能通过new运算符调用,而且构造方法是不返回任何数据类型,甚至也不返回void数据类型,即不能在构造方法前加void。 错误之处:(1)构造方法Student()前不能加void,(2)不能用return语句,(3)类名Student 首字母S改成小写s. 【4】定义一个表示学生的student类,包括的域有学号、姓名、性别、年龄,包括的方法有获得学号、姓名、性别、年龄及修改年龄。编写Java程序创建student类的对象及测试其方法的功能。 class Student { String id; String name; String sex; int age; void talk(){第3章 面向对象程序设计基础
(完整版)《面向对象程序设计》答案