C++程序设计(第二版 - 吴乃陵 - 况迎辉)课后答案

更新时间:2024-03-20 16:05:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第二章 基本控制结构程序设计习题 第二章 基本控制结构程序设计习题 1

一.基本概念与基础知识自测题 3.1 程序阅读题 3.1.1 设有说明: int a=3, b=100;

下面的循环语句执行 (1) 次,执行后a、b的值分别为 (2) 、 (3) 。 while(b/a>5){ if(b-a>25) a++; else b/=a;

} 解答: 本题检查学生整除的概念。跟踪: a b 3 100 4 100 5 100 ? ? 15 100 16 100 17 100 (1)14 (2)17 (3)100

b/a 220 6 6 5

循环次数 1 2 3 ? 131 4 停

b-a 96 95 ? 85 84

3.1.2 设有说明: int n,x,k,y;

下面程序段的功能是备选答案中的 (1) ,当n=10,x=10 打印结果是 (2) 。 cin>>x>>n; k=0; do{ x/=2; k++;

}while(k

n

y=1+x; k=0; do{ y=y*y; k++;

}while(k

n

(1 +y = x 2n)2 n

C. y = x )(1 + 2n n

D. y = x ) 2(1 +

2 n +1

第二章 基本控制结构程序设计习题

解答:

2

第一个循环使 x ;y 成为:1 ;第一个循环使 y 成x )

n x 2成为: x + ;为: (1 + nnn2 2 2

(1)B

考虑整除, 连除 4 次以后为零,所以:

x 2 n

(2)1

3.1.3 请看如下程序段: if(num==1) cout<<”Alpha”;

else if(num==2) cout<<”Bata”;

else if(num==3) cout<<”Gamma”; else cout<<”Delta”; 当num的值分别为 1、2、3 时,上面程序段的输出分别为(1) 、(2) 、(3) 。 解答:

检查条件语句与字符串输出概念: (1)Alpha (2)Bata (3)Gamma

3.1.4 执行下面程序段后,m和k的值分别为 (1) 、 (2) 。 int m,k;

for(k=1,m=0;k<=50;k++){ if(m>=10) break;

if(m%2==0){ m+=5; continue; } m-=3; }

解答:注意 continue 语句的使用 初值 m=1 k=第 1 次循环后 m=5 k=第 2 次循环 m=2 k=第 3 次循环 m=7 k=第 4 次循环 m=4 k=

第 5 次循环 第 6 次循环 第 7 次循环 (1)11 (2)6

m=9 m=6 m=11

k=k=

结束,k++未做

二.编程与综合练习题 3.2 编程求一元二次方程 ax2+bx+c=0 的根。包括以下判断和结果:若输入 a=0,给出提示;

3 第二章 基本控制结构程序设计习题

若Δ>0,输出两个不等实根;若Δ=0,输出两个相等实根;若Δ<0,输出两个复数根。

解:本题以一个绝对值极小的数作为实数 0。 #include #include #include void main(){ double a,b,c;

double delta,x1,x2;

const double zero=1e-9; //定义一个很小的常数 int sign;

cout<<\输入三个系数a(a!=0), b, c:\cin>>a>>b>>c;

if(fabs(a)

cout<<\<\if(fabs(delta)

cout<<\方程有两个相同实根:\cout<<\}

else {

if(delta>0) sign=1; else

sign=0;

delta=sqrt(fabs(delta));

x1=-b/(2*a); x2=delta/(2*a);

if(sign){ cout<<\方程有两个不同实根:\

cout<<\<

}

第二章 基本控制结构程序设计习题

cout<

6

}

3.6 输入 n,求 1!+2!+3!+…+n!

解:通常求和作为外循环,阶乘作为内循环。这里考虑到:n!=n*(n-1)!,利用递推法运算 速度大大提高,同时两者可合并为一个循环。本程序考虑了输入的健壮性。 #include #include void main(){ int n;

double result=0;//result是结果 cin>>n; if(n<1) {

cout<<\输入错误!\//return; exit(0); }

result=1;

for(int i=2,jch=1;i<=n;i++) {

jch*=i; //jch是i的阶乘,注意n!=n*(n-1)!这样可少一层循环

result+=jch; }

cout<

3.7 猴子吃桃问题:猴子摘下若干个桃子,第一天吃了桃子的一半多一个,以后每天吃了前

一天剩下的一半多一个,到第十天吃以前发现只剩下一个桃子,问猴子共摘了几个桃子。 解:采用递推法。从最后一天逆推到第一天,9 次循环。 #include const int day=10; void main(){

int i,x=1;//最后一天只有一个

for(i=1;i

cout<<\开始共有桃子\个。\\n\

}

3.8 从键盘输入一组非 0 整数,以输入 0 标志结束,求这组整数的平均值,并统计其中的个 数。 解:将这组整数放在整型数组中,一边输入一边求和及统计正数和负数的个数,平均数由和 除以整数数量取得。

7 第二章 基本控制结构程序设计习题

#include #include void main(){

int stem[256],sum=0,pnum=0,nnum=0,i=0; cout<<\从键盘输入一组非0整数,以输入0标志结束:\while(stem[i]!=0){ sum+=stem[i];//求和 if(stem[i]>0)

pnum++;//正数数量 else nnum++;//负数数量 i++;

cin>>stem[i]; }

if(!i) cout<<\个数\else { cout<<\平均值=

\double)sum/(pnum+nnum)<

3.9 编程找出 1~500 之中满足除以 3 余 2,除以 5 余 3,除以 7 余 2 的整数。

解:中国古代数学问题(韩信点兵),采用穷举法。注意三个条件同时成立用&&。

#include void main(){ int i; for(i=1;i<=500;i++)

if((i%3==2)&&(i%5==3)&&(i%7==2)) cout<

}

3.10 编程求 1000 之内的所有完全数。所谓完全数指的是一个数恰好等于它的所有因子和。 例如 6=1+2+3,就是一个完全数。 解:采用穷举法。两重循环,外层是从 1 到 999 依次处理,内层是求该数的所有因子的和, 并判断是否等于该数。

#include void main(){

int i,a,sum_yz; //sum_yz是

a的因子和

for(a=1;a<1000;a++){ sum_yz=0;

for(i=1;i

if (a%i==0) sum_yz+=i; if (a==sum_yz) cout<

8 第二章 基本控制结构程序设计习题

}

3.11 将 100 元换成用 10 元、5 元和 1 元的组合,共有多少种组合方法。 解:采用穷举法。考虑 10 元最多 10 张,5 元最多 20 张,余下是 1 元。 #include void main(){

for(int i=0,j,k,count=0;i<=10;i++)//i是10元张数,j是5元张数,k是1元张数 for(j=0;j<=20;j++){ k=100-10*i-5*j;

if(k>=0){

cout<

cout<

3.12 利用反正切展开计算π的近似值,要求误差 10-5,公式如下:

3 5

x 7 x x

arctg ( x) ≈ x ? + ? + L

3 5 7

令 x=1,可计算出π/4 的近似值。 解:采用递推法。初看每一项的递推通式不易写出,但每一项全看作奇数项,而偶数项全为 零,则很容易写出:第 1 项为 x,第 3 项为第 1 项乘以 x 的平方除以项序号 3 乘以-1,其余 类推。同时和的误差小于最后一项的绝对值。

#include #include const double e=1e-6;

void main(){

double x,a,sum; int i=3; cout<<\请输入弧度值:\cin>>x; a=x; sum=

x; do{

a*=x*x*(-1);

sum+=a/i; i+=2;

}while(fabs(a/i)>e);

cout<<\}

9 第二章 基本控制结构程序设计习题

3.13 用迭代法求方程x2+10cosx=0 的根,误差限为 10-5。迭代公式如下:

2 ? x 10( x sin nx + cos x ) n n n n x +1 = 2 ? 10 sin xn xn

解:迭代法也是用循环语句实现,数学上 #include #include const double e=1e-5; void main(){

float x0,x1; int n=0; cout<<\输入初始近似值:\do{

x0=x1;

x1=(x0*x0-10*(x0*sin(x0)+cos(x0)))/(2*x0-10*sin(x0));

//x0是上次算出的结果,x1用作保存

新算出的结果

n++;

}while((fabs(x1-x0) >e)&&(n<=1e5)); if(n>1e5)

cout<<\超出迭代1e5次\\n\else cout<<\方程x*x+10*cos(x)=0的一个根为:\cout<<\方程误差为:\}

3.14 两队选手每队 5 人进行一对一的比赛,甲队为 A、B、C、D、E,乙队为 J、K、L、M、 N,经过抽签决定比赛配对名单。规定 A 不和 J 比赛,M 不和 D 及 E 比赛。列出所有可能 的比赛名单。 解:这是一个组合问题,使用穷举法。共有 5 个位置,设甲队 5 名队员位置不变,乙队改变 队员位置,进行配对。注意第 1 个位置可在 5 个队员中任选一个,以后的位置必须扣除已选 过的队员。并扣除不能配对的情况,即得所有可能的比赛名单。 #include void

main(){ char

st1[5]={'A','B','C','D','E'},st2[5]={'J','K','L','M','N'};

int i=0,j,k,l,m,n;

for(j=0;j<5;j++){//0号位

if(j==0) continue;//A不与J比赛,即st1[0]

不与st2[0]比赛

for(k=0;k<5;k++){//1号位 if(k==j) continue;

for(l=0;l<5;l++){//2号位

if(l==j||l==k) continue; for(m=0;m<5;m++){//3号位

if(m==j||m==k||m==l)

continue;

第二章 基本控制结构程序设计习题 10

if(m==3) continue;//M不与D比赛,即st1[3]不与st2[3]比赛

for(n=0;n<5;n++){//4号位

if(n==3) continue;//M不与E比赛,即st1[4]不与st2[3]比赛

if(n==j||n==k||n==l||n==m) continue; cout<

cout<

cout<

}

cout<

}

3.15 编程模拟选举过程。假定四位候选人:zhang、wang、li、zhao,代号分别为 1、2、3、

4。选举人直接键入候选人代号,1~4 之外的整数视为弃权票,-1 为终止标志。打印各位候 选人的得票以及当选者(得票数超过选票总数一半)名单。 解:用 5 个元素的整型数组,分别放弃权票和各候选人的得票,然后用开关语句打印。 #include #include void main(){

enum candidate{feipiao,zhang,wang,li,zhao}cand; int vote[5]={0},i,k=0,n;

cin>>n;

while(n!=-1){ k++;

if(n>=1&&n<=4) vote[n]++; else vote[0]++; cin>>n;

}

for(i=0;i<5;i++){ cand=(candidate)i;

switch(cand){ case feipiao:

cout<

zhang:cout<k/2) cout<<\当选\else cout<

case wang:cout<k/2) cout<<\当选\

第二章 基本控制结构程序设计习题 11

else cout<

li:cout<k/2) cout<<\当选\else cout<

case zhao:cout<k/2) cout<<\当选\else cout<

}

3.16 改造【例 3.11】,将运行结果(Fibonacii 数列的前 20 项)存入文件。 解:采用 3 步法。首先建立或打开一个输出文件,并与磁盘文件联系:

ofstream ofile(\再按一定格式存入数据:

ofile<

ifstream

ifile(\再按同一格式读入数据:ifile>>i>>j>>k>>l;等,并输出 最后关闭文件:file.close(); #include #include const int m=20; void main(){

int fib0=0,fib1=1,fib2,i,j,k,l; char ch,a[256]; ofstream

ofile(\ofile<

n=3;n<=m;n++){ fib2=fib0+fib1;

ofile<

fib0=fib1; fib1=fib2; } ofile.close(); cout<<\是否要将文件输出?Y或N\if(ch=='y'||ch=='Y'){

ifstream ifile(\while(1){

ifile>>i>>j>>k>>l;//由文件读入

第二章 基本控制结构程序设计习题 12

if(ifile.eof()!=0) break;

cout<

ifile.close(); }

}

3.17 改造【例 3.16】,将运行结果(100 以内素数)存入文件。 解:采用 4 步法。首先定义一个输出文件:ofstream ofile; 再打开该文件并与并与磁盘文件联系:ofile.open(\按一定格式把数据存入文件。最后关闭文件。效果与 3 步法相同。 读文件同样可用 3 步法或 4 步法。 #include #include #include const int n=100; void main(){ int

a[n],i,j; char

ch,b[256]; ofstream ofile; ifstream ifile;

for(i=0;i

for(j=i+1;j

ofile.open(\

17.txt\int count=0;

ofile<<\之间的素数:\for(i=0;iif(count==0) ofile<

} ofile.close(); cout<<\是否要将文件输出?Y或N\

if(ch=='y'||ch=='Y'){ ifile.open(\7.txt\

while(ifile.get(b[i])){//不可用>>,它不能读白字符,

第二章 基本控制结构程序设计习题

if(b[i]=='\\n') break; i++;

13

}

b[i]='\\0'; cout<

count=0; while(1){

ifile>>i;//由文件读入

cout<

//这里与例3.20不同,最后一个数据后面可能没有回车,直接为文件结束 }

ifile.close();

cout<

}

3.18 改造【例 3.10】,文本由文本文件输入。

解:文本文件读入要用成员函数: ifile.get(),而不可用插入运算符<<,否则会丢失空白字 符。 #include void main(){ char ch; int

nline=0,nword=0,nch=0; int

isword=0; ifstream

ifile(\cout<<\读入ep3_18.cpp\do{

ch=ifile.get(); if(ch=='\\n') nline++; //遇换行符行数+1 if(ch!='

'&&ch!='\\t'&&ch!='\\n'&&ch!=EOF){ //读到非间隔符

if(!isword) nword++; //在单词的起始处给单词数+1 nch++; //字符数加+1 isword=1; } else isword=0; //读到间隔符 }while(ch!=EOF); //读到文本结束符为止

ifile.close(); cout<<\行数:\cout<<\单词数:\cout<<\字符数:\}

第二章 基本控制结构程序设计习题 14

第四章 类与对象习题 1

第四章 类与对象习题

一. 基本概念与基础知识自测题 4.1 填空题

5.1.1 引入类定义的关键字是 (1) 。类的成员函数通常指定为 (2) ,类的 数据成员通常指定为 (3) 。指定为 (4) 的类成员可以在类对象所在域 中的任何位置访问它们。通常用类的 (5) 成员表示类的属性,用类的 (6) 成员表示类的操作。 答案:

(1) class (2) 公有的 public (3) 私有的 private (4) 公有的 public (5) 数据 (6) 函数

4.1.2 类的访问限定符包括 (1) 、 (2) 和 (3) 。私有数据通常由 (4) 函数来访问(读和写)。这些函数统称为 (5) 。 答案:

(1) public(公有的) (2) private(私有的) (3) protected(保护的) (4) 公有的成员函数 (5) 类的接口

4.1.3 通常在逻辑上,同一类的每个对象都有 (1) 代码区,用以存储成员函数。而 在物理上通常只有 (2) 代码区。只有在 (3) 定义,并 (4) 的 函数和加了关键字 (5) 的函数例外。 答案:

(1) 独立的 (2) 共用的 (3) 在类说明中

(4) 不包括循环等复杂结构 (5) inline

4.1.4 C++中支持三种域: (1) 、 (2) 、 (3) 。函数域被包括在

(4) 中,全局域被包括在 (5) 中。using指示符以关键字using开头,后面 是关键字 (6) ,最后是 (7) 。这样表示以后在该名字空间中所有成员都 (8)

。如不使用using指示符则在使用时要加::,称为 (9) 运算符。 答案:

(1) (2) (3) (4) (5) (6) (7) 局部域(local scope)

名字空间域(namespace scope) 类域(class scope) 局部域 名字空间域 namespace 名字空间名

2 第四章 类与对象习题

(8) 可以直接被使用 (9) 域

4.1.5 引用通常用作函数的 (1) 和 (2) 。对数组只能引用 (3)不能引用 (4) 。 答案: (1) 参数 (2) 返回值 (3) 数组元素 (4) 数组名本身 4.1.6 构造函数的任务是 (1) 。构造函数无 (2) 。类中可以有 (3) 个构造函数,它们由 (4) 区分。如果类说明中没有给出构造函数,则C++编译 器会 (5) 。拷贝构造函数的参数是 (6) ,当程序没有给出复制构造函 数时,系统会自动提供 (7) 支持,这样的复制构造函数中每个类成员 (8) 。 答案:

(1) 初始化数据成员 (2) 函数返回类型说明 (3) 多

(4) 不同的参数表

(5) 自动给出一个默认的构造函数 (6) 同一类对象的引用

(7) 默认的的复制构造函,称为默认的按成员语义支持。 (8) 被依次复制 4.1.7 一个类有 (1) 个析构函数。 (2) 时,系统会自动调用析构函数。 答案: (1) 一

(2) 对象注销时

4.1.8 运算符重载时,其函数名由 (1) 构成。成员函数重载双目运算符时,左操作 数是 (2) ,右操作数是 (3) 。 答案: (1) 关键字 operator 和该运算符 (2) 对象

(3) 该函数的参数

4.1.9 面向过程的程序设计中程序模型描述为 (1) ,面向对象程序设计的程序模型可描 述为 (2) 。 答案: (1)“程序=算法+数据结构”。其数据与数据处理是分离的。 (2)程序=(对象+对象+……+对象)+消息;对象=(算法+数据结构)。面向对象设计将数 据和对数据的操作方法放在一起,形成一个相对独立的整体——对象(Object),并通 过简单的接口与外部联系。对象之间通过消息(Message)进行通讯。

4.2 简答题

4.2.1 简单解释什么是面向对象程序设计的封装性。 答:对象是一个封装体,在其中封装了该对象所具有的属性和操作。对象作为独立的基本单 元,实现了将数据和数据处理相结合的思想。此外,封装特性还体现在可以限制对象中数据

3 第四章 类与对象习题

和操作的访问权限,从而将属性“隐藏”在对象内部,对外只呈现一定的外部特性和功能。

封装性增加了对象的独立性,C++通过建立数据类型——类,来支持封装和数据隐藏。 一个定义完好的类一旦建立,就可看成完全的封装体,作为一个整体单元使用,用户不需要 知道这个类是如何工作的,而只需要知道如何使用就行。另一方面,封装增加了数据的可靠 性,保护类中的数据不被类以外的程序随意使用。这两个优点十分有利于程序的调试和维护。

4.2.2 C++编译器怎样对标识符进行解析? 答:编译器对标识符的解析分两步,第一步查找在声明中用到的标识符,特别是函数成员声 明中用到的参数类型,第二步是函数成员体内的标识符。

4.2.3 为什么说类与对象的概念是客观世界的反映? 答:客观世界的事物都具有某些属性和行为(或操作),具有相同属性和行为的事物可以归 属于一类,用分类的方法可以提高认识事物的效率。C++中定义的类则是通过抽象的方法将 某一类事物共有的静态特征(属性)和动态特征(行为)概括出来并加以描述,而对象是类 的具体实现,所以说类与对象的概念是客观世界的反映。

4.2.4 什么叫类域?为什么说类域是抽象的? 答:类域是类体所包括的范围。每个类定义都引入了一个独立的类域,在类域中说明的标识 符仅在该类的类域中有效。由于类只是一个说明,看上去有数据,有函数,有类型定义,但 是它并非实体,不分配内存,当然也不能运行。所以说类域是抽象的。

4.2.5 引用作为函数参数时为什么能实现两个实参之间的数据交换?为什么对应实参不能 为引用?为什么返回值为引用的函数可以作为左值? 答:引用变量是其关联变量的别名,二者在内存中占据同一个存储单元。在一个以引用作为 参数的函数中,交换两个参数的值,实际上就是交换两个实参的值。如果函数的参数是引用, 调用时需要取得实参的地址,而实参如果已经是一个地址,再进行引用将产生错误,故对应 实参不能为引用。 函数返回引用实际是指明(返回)了相应的关联变量,所以声明返回值为引用的函数实

际上是将关联变量作为左值参与运算。

4.2.6 什么是缺省的构造函数?缺省的构造函数最多可以有多少个? 答:如果在类定义中不显式地定义构造函数,C++编译器会自动产生一个缺省的构造函数, 不过该函数不做具体的初始化工作。只要构造函数是无参的或者只要各参数均有缺省值的, C++编译器都认为是缺省的构造函数。缺省的构造函数只能有一个。

4.2.7 拷贝构造函数用于哪三个方面? 答:

(1) 用类的一个对象去初始化该类的另一个对象时使用。 (2) 当函数的形参是类的对象,调用函数时,进行形参与实参结合时使用。

(3) 当函数的返回值是类对象,函数执行结束返回调用者时使

用。

4.2.8 写出含有对象成员的类的构造函数的格式,并做简单说明。 答:C++中对含对象成员的类对象的构造函数有固定的格式: 类名::构造函数名(参数总表):对象成员 1(参数名表 1),对象成员 2(参数名表 2),……对象成

4 第四章 类与对象习题

员 n(参数名表 n){……}

冒号后用逗号隔开的是要初始化的对象成员,附在后面的参数名表 1,…,参数名表 n 依次 为调用相应对象成员所属的构造函数时的实参表。这些表中的参数通常来自冒号前的参数总 表,但没有类型名。

4.2.9 所有类对象未重载的赋值运算符“=”是怎样工作的?为什么它可以进行连续赋值? 答:对所有的类对象,未重载的赋值运算符“ =”称作缺省的按成员拷贝赋值操作符,同类 对象之间可以用“=”直接拷贝。因为缺省的赋值操作返回一个对象的引用,所以它可以进 行连续赋值。

4.2.10 为什么在友元函数的函数体内访问对象成员时,必须用对象名加运算符“.”再加对 象成员名? 答:友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符“.” 加对象成员名。这一点和一般函数一样。

4.2.11 重载复数运算符+时,采用下面友元函数

声明: friend Complex operator+(Complex &c1,Complex &c2); 为什么不能用于“实数+复数”?怎样改进才能适用?为什么? 答:使用引用类型变量作为运算符重载函数的参数,身为左值的实数类型实参不能被转换为 复数,编译时无法通过。添加 const 说明,使实数到复数的转换隐式地在一份拷贝上进行, 则可以实现“实数+复数”运算。修改后的说明为:

friend Complex operator+(const Complex &c1, const Complex &c2);

4.2.12 类的静态数据成员与函数中的静态成员有何异同? 答:类的静态成员为其所有对象共享,不管有多少对象,静态成员只有一份存于公用内存中, 为该类所有对象公用。函数中的静态变量也位于公用内存中,不随函数调用而重新分配,所 以总是保留上次进入并执行该函数后留下的信息。

4.2.13 C++中结构、联合与类三者间有何异同?

答:在 C++中结构(structure)与类几乎是完全一样的类型,差别仅仅在于缺省情况下结构 的成员为公有的。联合(union)是 C++的导出数据类型,在语法与功能上类似于结构,二 者的区别是:结构变量的各成员同时被分配了各自独立的内存区,而联合变量的各个成员的 存储开始地址都相同,所以在任一时刻联合变量只能存储一个成员。

4.2.14 对象的第一特征是封装,那么由对象组成的面向对象的程序怎样建立各对象之间的 有效联系?面向对象程序的组织与面向过程有什么不同? 答:因为对象的操作主要用来响应外来消息并为其他对象提供服务,所以面向对象的程序利 用消息传递机制来建立各对象之间的有效联系,协调各对象的运行。一个对象可以向其他对 象发送消息以请求服务,也可以响应其他对象传来的消息,完成自身固有的某些操作,从而 服务于其他对象。 面向过程的程序是模块化的,模块的组织具有分层结构特点,层与层之间是调用关系。

面向对象程序是由一个个封装的对象组成,而对象是由紧密结合在一起的算法和数据结构组 成。对象之间是相互请求和相互协

作的关系。

5 第四章 类与对象习题

4.2.15 简叙 Windows 下应用程序的运行方式。

答:Windows 系统支持多个应用程序同时执行,在界面形式上,它支持多个窗口同时活动。 它的运行机制是“消息传递和事件驱动(message based and event driven)”。

Windows 系统使用事件驱动的编程模式。所谓事件的含义非常广泛。输入设备的动作, 如敲打键盘、按鼠标等会产生一系列的事件(注意不是一个事件)。操作系统所作的一举一 动也被当作某种类型的事件,应用程序也会产生各种事件。事件用来标识发生的某件事情。

Windows 系统对于应用程序环境中发生的每一个事件都会以对应的某种消息的形式标 识,并放入相应的 Windows 建立的消息队列中,然后由对应的应用程序或窗口函数去处理。 窗口函数处理是分层的,前面处理不了的送到后面,最后处理不了剩下的全由缺省的窗口函 数处理。

4.2.16 类的成员函数在什么情况下应该定义为私有的?这样做的目的是什么? 答:除接口函数和创建本类对象的构造函数和撤消该对象的析构函数外。其余成员函数应该 定义为私有的,这是开发类时故意对外隐蔽起来的操作,而这些往往是最复杂最关键的部分。 类中故意的隐藏也为以后的升级扩展留下了余地,只要接口不变,内部再变,也不必修改原 来的程序,就象 MFC(微软基础类)升级后,由 MFC 底层类所编的程序完全不必修改,自 动升级。

二.编程与综合练习题

4.3 构造一个日期时间类(Timedate),数据成员包括年、月、日和时、分、秒,函数成员 包括设置日期时间和输出时间,其中年、月请用枚举类型,并完成测试。(包括用成员 函数和用普通函数)

解:本题要求仅是定义类的练习,并非实用的提供日期时间的程序。实用的日期时间程序 见附录二的日期时间函数。 #include #include using namespace std;

enum YR{Y2000,Y2001,Y2002,Y2003,Y2004,Y2005};//

enum MT{Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec}; class Timedate{ private:

YR year; MT month;

int date; int hh; int mm; int ss; public:

Timedate(){year=Y2000;month=Jan;date=1;hh=0;mm=0;ss=0;} Timedate(YR a,MT b,int c){

year=a; month=b; date=c;

hh=12;mm=30;ss=0;

第四章 类与对象习题

}

void getdate(YR &,MT &,int &);//使用引用一次取得3个数值 void gettime(int &,int &,int &); void

putdate(YR ,MT ,int ); void

puttime(int ,int ,int ); void list();

6

};

void Timedate::getdate(YR &y,MT &m,int &d){ y=year; m=month; d=date; }

void Timedate::gettime(int &a,int &b,int &c){ a=hh; b=mm; c=ss; }

void Timedate::putdate(YR a,MT b,int c){ year=a; month=b; date=c; }

void Timedate::puttime(int a,int b,int c){ hh=a; mm=b; ss=c; }

void Timedate::list(){//成员函数,直接访问私有的数据成员 cout<<\switch(year){ case

Y2000:cout<<\break; case Y2001:cout<<\break; case Y2002:cout<<\break; case Y2003:cout<<\break; case Y2004:cout<<\break; case Y2005:cout<<\break; }

switch(month){ case

Jan:cout<<'/'<<\break; case

Feb:cout<<'/'<<\break; case

Mar:cout<<'/'<<\break; case

Apr:cout<<'/'<<\break; case

May:cout<<'/'<<\break; case

Jun:cout<<'/'<<\break;

第四章 类与对象习题

7

case

Jul:cout<<'/'<<\break; case

Aug:cout<<'/'<<\break; case

Sep:cout<<'/'<<\break; case

Oct:cout<<'/'<<\break; case

Nov:cout<<'/'<<\break; case

Dec:cout<<'/'<<\break;

} cout<<'/'<

cout<

}

int main(int argc, char* argv[]){ Timedate A(Y2004,Mar,3),B; A.list(); B.list();

B.putdate(Y2005,Oct,18);

B.puttime(17,30,00); B.list(); return 0; }

4.4 设计并测试一个矩形类(

Rectangle),属性为矩形的左下与

右上角的坐标,矩形水平 放置。操作为计算矩形周长与面积。测试包括用成员函数和普通函数。 解:这里的矩形的 4 边分别与 x 轴 y 轴平行,为最简单的情况。注意参数有缺省值的函数 的声明和定义格式。 #include #include

using namespace std; class

Rectangle {

double left, top ; double right, bottom; public:

Rectangle(double l=0, double t=0, double r=0, double b=0); ~ Rectangle(){}; //析构函数,在此函数体为空 void Assign(double l,double t,double r,double b);

double getLeft(){ return left;} // 以下四个函数皆为内联成员函数

double getRight(){ return right;} double getTop(){return top;}

double getBottom(){return bottom;} void Show(); double Area(); double

Perimeter(); };

8 第四章 类与对象习题

// 构造函数,带缺省参数,缺省值为全0,在声明中指定 Rectangle::Rectangle(double l , double t, double r, double b) { left = l; top = t;

right = r; bottom = b; }

void Rectangle::Assign(double l, double t, double r, double b){//赋值 left = l; top = t;

right = r; bottom = b; }

void Rectangle::Show(){//成员函数直接使用私有的数据成员 cout<<\(\cout<<\

(\}

double Rectangle::Area(){

return fabs((right-left)*(bottom-top)); }

double Rectangle::Perimeter(){

return 2*(fabs(right-left)+fabs(bottom-top)); } int

main(){ Rectangle rect;

rect.Show();

rect.Assign(100,200,300,400); rect.Show();

Rectangle rect1(0,0,200,200); rect1.Show(); Rectangle rect2(rect1); rect2.Show();

cout<<\面积\周长\

return 0; }

4.5 定义一个圆类(Circle),属性为半径(radius)、圆周长和面积,操作为输入半径并计 算周长、面积,输出半径、周长和面积。要求定义构造函数(以半径为参数,缺省值为 0, 周长和面积在构造函数中生成)和拷贝构造函数。 解:通常所有数据成员都在构造函数中赋初值。拷贝构造函数以本类的引用为参数。 #include #include using

namespace std; class Circle{

double r,Area,Circumference; public:

Circle(double a=0);

第四章 类与对象习题

Circle(Circle &);

void SetR(double R); double GetR(){return r;}

double GetAreaCircle(){return Area;}

double GetCircumference(){return Circumference;}

9

};

Circle::Circle(double a){ r=a;

Area=r*r*3.14159265;

Circumference=2*r*3.14159265; }

Circle::Circle(Circle & cl){ r=cl.r; Area=cl.Area; Circumference=cl.Circumference; }

void

Circle::SetR(double R){ r=R; Area=r*r*3.14159265;

Circumference=2*r*3.14159265; }

int main(){

Circle cl1(2),cl2,cl3=cl1;

cout<<\圆半径:\圆周长:\

<<'\\t'<<\圆面积:\cl2.SetR(4); cout<<\圆半径:\圆周长:\

<<'\\t'<<\圆面积:\ return 0; }

4.6 设计一个学校在册人员类(Person)。数据成员包括:身份证号(IdPerson),姓名(Name), 性别(Sex),生日(Birthday)和家庭住址(HomeAddress)。成员函数包括人员信息的录入 和显示。还包括构造函数与拷贝构造函数。设计一个合适的初始值。 解:本题为指出构造函数等的调用,加了一些提示语句。 #include #include using namespace std;

enum Tsex{mid,man,woman};

class Person{

char IdPerson[19]; //身份证号,18位数字

第四章 类与对象习题 10

char Name[20]; //姓名 Tsex Sex; //性别 int Birthday; //生日,格式1986年8月18日写作19860818 char HomeAddress[50]; //家庭地址 public:

Person(char *,char *,Tsex,int,char *); Person(Person &); Person(); ~Person();

void PrintPersonInfo(); void inputPerson(); //其他接口函数 };

Person::Person(char *id,char *name,Tsex sex,int birthday,char *homeadd){ cout<<\构造Person\strcpy(IdPerson,id); strcpy(Name,name); Sex=sex;

Birthday=birthday;

strcpy(HomeAddress,homeadd); }

Person::Person(){

cout<<\缺省构造Person\IdPerson[0]='\\0';Name[0]='\\0';Sex=mid;

Birthday=0;HomeAddress[0]='\\0'; }

Person::Person(Person & Ps){ cout<<\拷贝构造Person\

strcpy(IdPerson,Ps.IdPerson);

strcpy(Name,Ps.Name); Sex=Ps.Sex;

Birthday=Ps.Birthday;

strcpy(HomeAddress,Ps.HomeAddress); }

Person::~Person(){

cout<<\析构Person\ }

void Person::inputPerson(){ char ch; cout<<\请输入身份证号,18位数字:\

cin.getline(IdPerson,19); cout<<\请输入姓名:\

cin.getline(Name,20); cout<<\请输入性别m或w:\

第四章 类与对象习题

cin>>ch;

if(ch=='m') Sex=man; else Sex=woman;

cout<<\请输入生日,格式1986年8月18日写作19860818:\cin.get(); //吸收回车符,否则地址输不进去 cout<<\请输入地址:\

cin.getline(HomeAddress,50);

11

}

void Person::PrintPersonInfo(){ int i; cout<<\身份证号:\姓名:\性别:\if(Sex==man)cout<<\男\else if(Sex==woman)cout<<\女\

else cout<<\\出生年月日:\i=Birthday;

cout<

cout<

int main(){

Person Ps1(\朱海鹏

\南京市黄浦路1号\Ps1.PrintPersonInfo();

Ps2.PrintPersonInfo();

Ps3.inputPerson();

Ps3.PrintPersonInfo(); return 0; }

4.7 对上面 4 道题中的类对象的数据,由友元函数来进行访问。并对比友元函数、成员函 数和普通函数使用上的不同。 解:友元函数可直接访问私有成员。友元函数在类中声明时不问访问权限。仅以 5.4 题为例。 #include #include

using

namespace std; class

Rectangle {

double left, top ; double right, bottom; public:

Rectangle(double l=0, double t=0, double r=0, double b=0); ~ Rectangle(){}; //析构函数,在此函数体为空

第四章 类与对象习题 12

void Assign(double l,double t,double r,double b);

double getLeft(){ return left;} // 以下四个函数皆为内联成员函数

double getRight(){ return right;} double getTop(){return top;}

double getBottom(){return bottom;} void Show();

friend void showprint(Rectangle); double Area(); double Perimeter(); };

// 构造函数,带缺省参数,缺省值为全0,在声明中指定 Rectangle::Rectangle(double l , double t, double r, double b) { left = l; top = t;

right = r; bottom = b; }

void Rectangle::Assign(double l, double t, double r, double b){//赋值 left = l; top = t;

right = r; bottom = b; }

double Rectangle::Area(){

return fabs((right-left)*(top-bottom)); }

double Rectangle::Perimeter(){

return 2*(fabs(right-left)+fabs(top-bottom)); }

void Rectangle::Show(){//成员函数

cout<<\

cout<<\ }

void showprint(Rectangle rt){//友元函数,要加类名,但直接调用私有数据成员

cout<<\cout<<\

(\ }

void print(Rectangle rt){//普通函数,要用接口函数间接调

本文来源:https://www.bwwdw.com/article/jzo8.html

Top