C++第五章 类与对象习题解答
第五章类与对象习题
一.基本概念与基础知识自测题
5.1 填空题
5.1.1 引入类定义的关键字是(1)。类的成员函数通常指定为(2),类的
数据成员通常指定为(3)。指定为(4)的类成员可以在类对象所在域中的任何位置访问它们。通常用类的(5)成员表示类的属性,用类的(6)成员表示类的操作。
答案:
(1)class
(2)公有的public
(3)私有的private
(4)公有的public
(5)数据
(6)函数
5.1.2 类的访问限定符包括(1)、(2)和(3)。私有数据通常由
(4)函数来访问(读和写)。这些函数统称为(5)。
答案:
(1)public(公有的)
(2)private(私有的)
(3)protected(保护的)
(4)公有的成员函数
(5)类的接口
5.1.3 通常在逻辑上,同一类的每个对象都有(1)代码区,用以存储成员函数。而
在物理上通常只有(2)代码区。只有在(3)定义,并(4)的函数和加了关键字(5)的函数例外。
答案:
(1)独立的
(2)共用的
(3)在类说明中
(4)不包括循环等复杂结构
(5)inline
5.1.4 C++中支持三种域:(1)、(2)、(3)。函数域被包括在
(4)中,全局域被包括在(5)中。using指示符以关键字using开头,后面是关键字(6),最后是(7)。这样表示以后在该名字空间中所有成员都(8)。如不使用using指示符则在使用时要加::,称为(9)运算符。
答案:
(1)局部域(local scope)
(2)名字空间域(namespace scope)
(3)类域(class scope)
(4)局部域
(5)名字空间域
(6)namespace
(7)名字空间名
(8)可以直接被使用
(9)域
5.1.5 引用通常用作函数的(1)和(2)。对数组只能引用(3)不能引用(4)。答案:
(1)参数
(2)返回值
(3)数组元素
(4)数组名本身
5.1.6 构造函数的任务是(1)和(2)。构造函数无(3),但并不
表示(4)。类中可以有(5)个构造函数,它们由(6)区分。
如果类说明中没有给出构造函数,则C++编译器会(7)。拷贝构造函数的参数是(8),当程序没有给出拷贝构造函数时,系统会自动提供(9)支持,这样的拷贝构造函数中每个类成员(10)。
答案:
(1)建立对象(为对象分配内存)
(2)初始化数据成员
(3)函数返回类型说明
(4)没有返回值,返回的是构造函数所创建的对象
(5)多
(6)不同的参数表
(7)自动给出一个缺省的构造函数
(8)同一类对象的引用
(9)缺省的拷贝构造函,称为缺省的按成员语义支持。
(10)被依次拷贝
5.1.7 一个类有(1)个析构函数。(2)时,系统会自动调用析构函数。答案:
(1)一
(2)对象注销时
5.1.8 运算符重载时,其函数名由(1)构成。成员函数重载双目运算符时,左操作
数是(2),右操作数是(3)。
答案:
(1)关键字operator和该运算符
(2)对象
(3)该函数的参数
5.2简答题(以下习题题号可能和教材不一致!)
5.2.1为什么返回值为引用的函数可以作为左值?
答:函数返回引用实际是指明(返回)了相应的关联变量,所以声明返回值为引用的函数实际上是将关联变量作为左值参与运算。
5.2.2什么是缺省的构造函数?缺省的构造函数最多可以有多少个?
答:如果在类定义中不显式地定义构造函数,C++编译器会自动产生一个缺省的构造函数,不过该函数不做具体的初始化工作。只要构造函数是无参的或者只要各参数均有缺省值的,
C++编译器都认为是缺省的构造函数。缺省的构造函数只能有一个。
5.2.3拷贝构造函数用于哪三个方面?
答:
(1)用类的一个对象去初始化该类的另一个对象时使用。
(2)当函数的形参是类的对象,调用函数时,进行形参与实参结合时使用。
(3)当函数的返回值是类对象,函数执行结束返回调用者时使用。
5.2.4所有类对象未重载的赋值运算符“=”是怎样工作的?为什么它可以进行连续赋值?答:对所有的类对象,未重载的赋值运算符“ =”称作缺省的按成员拷贝赋值操作符,同类对象之间可以用“=”直接拷贝。因为缺省的赋值操作返回一个对象的引用,所以它可以进行连续赋值。
5.2.5为什么在友元函数的函数体内访问对象成员时,必须用对象名加运算符“.”再加对
象成员名?
答:友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员名。这一点和一般函数一样。
5.2.6重载复数运算符+时,采用下面友元函数声明:
friend Complex operator+(Complex &c1,Complex &c2);
为什么不能用于“实数+复数”?怎样改进才能适用?为什么?
答:使用引用类型变量作为运算符重载函数的参数,身为左值的实数类型实参不能被转换为复数,编译时无法通过。添加const说明,使实数到复数的转换隐式地在一份拷贝上进行,则可以实现“实数+复数”运算。修改后的说明为:
friend Complex operator+(constr Complex &c1, const Complex &c2);
5.2.7C++中结构、联合与类三者间有何异同?
答:在C++中结构(structure)与类几乎是完全一样的类型,差别仅仅在于缺省情况下结构的成员为公有的。联合(union)是C++的导出数据类型,在语法与功能上类似于结构,二者的区别是:结构变量的各成员同时被分配了各自独立的内存区,而联合变量的各个成员的存储开始地址都相同,所以在任一时刻联合变量只能存储一个成员。
二.编程与综合练习题
5.3 构造一个日期时间类(Timedate),数据成员包括年、月、日和时、分、秒,函数成员
包括设置日期时间和输出时间,其中年、月请用枚举类型,并完成测试。(包括用成员函数和用普通函数)
解:本题要求仅是定义类的练习,并非实用的提供日期时间的程序。实用的日期时间程序见附录二的日期时间函数。
#include
#include
#include
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 &);//体会用引用的优点
void gettime(int &,int &,int &);
void putdate(YR ,MT ,int );
void puttime(int ,int ,int );
void list();
};
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<<"year/month/date :";
switch(year){
case Y2000:cout<<"2000";break;
case Y2001:cout<<"2001";break;
case Y2002:cout<<"2002";break;
case Y2003:cout<<"2003";break;
case Y2004:cout<<"2004";break;
case Y2005:cout<<"2005";break;
}
switch(month){//,,,,,,,,
case Jan:cout<<'/'<<"Jan";break;
case Feb:cout<<'/'<<"Feb";break;
case Mar:cout<<'/'<<"Mar";break;
case Apr:cout<<'/'<<"Apr";break;
case May:cout<<'/'<<"May";break;
case Jun:cout<<'/'<<"Jun";break;
case Jul:cout<<'/'<<"Jul";break;
case Aug:cout<<'/'<<"Aug";break;
case Sep:cout<<'/'<<"Sep";break;
case Oct:cout<<'/'<<"Oct";break;
case Nov:cout<<'/'<<"Nov";break;
case Dec:cout<<'/'<<"Dec";break;
}
cout<<'/'< cout<<"hour:minite:second :"; cout< } int main(){ Timedate A(Y2004,Mar,3),B; A.list(); B.list(); B.putdate(Y2005,Oct,18); B.puttime(17,30,00); B.list(); } 5.4设计并测试一个矩形类(Rectangle),属性为矩形的左下与右上角的坐标,矩形水平放 置。操作为计算矩形周长与面积。测试包括用成员函数和普通函数。 解:这里的矩形的4边分别与x轴y轴平行,为最简单的情况。注意参数有缺省值的函数的声明和定义格式。 #include #include 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(); }; // 构造函数,带缺省参数,缺省值为全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<<"left-top point is ("< cout<<"right-bottom point is ("< } double Rectangle::Area(){ return fabs((right-left)*(bottom-top)); } double Rectangle::Perimeter(){ return 2*(fabs(right-left)+fabs(bottom-top)); } void print(Rectangle rt){//普通函数 cout<<"left-top point is ("< cout<<"right-bottom point is ("< } void 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(); print(rect); cout<<"面积"< } 5.5定义一个圆类(Circle),属性为半径(radius)、圆周长和面积,操作为输入半径并计 算周长、面积,输出半径、周长和面积。要求定义构造函数(以半径为参数,缺省值为0,周长和面积在构造函数中生成)和拷贝构造函数。 解:通常所有数据成员都在构造函数中赋初值。拷贝构造函数以本类的引用为参数。 #include #include 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;} }; 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; } void main(){ Circle cl1(2),cl2,cl3=cl1; cout<<"圆半径:"< cl2.SetR(4); cout<<"圆半径:"< } 5.6设计一个学校在册人员类(Person)。数据成员包括:身份证号(IdPerson),姓名(Name), 性别(Sex),生日(Birthday)和家庭住址(HomeAddress)。成员函数包括人员信息的录入和显示。还包括构造函数与拷贝构造函数。设计一个合适的初始值。 解:本题为指出构造函数等的调用,加了一些提示语句。 #include #include enum Tsex{mid,man,woman}; class Person{ char IdPerson[19]; //身份证号,18位数字 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,https://www.360docs.net/doc/a47871119.html,); Sex=Ps.Sex; Birthday=Ps.Birthday; strcpy(HomeAddress,Ps.HomeAddress); } Person::~Person(){ cout<<"析构Person"< } void Person::inputPerson(){ char id[19]; //身份证号,18位数字 char name[20]; //姓名 Tsex sex; //性别 int birthday; //生日,格式1986年8月18日写作19860818 char homeadd[50]; char ch; cout<<"请输入身份证号,18位数字:"< cin.getline(id,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>>birthday; cout<<"请输入地址:"< cin.getline(homeadd,50); strcpy(IdPerson,id); strcpy(Name,name); Sex=sex; Birthday=birthday; strcpy(HomeAddress,homeadd); } void Person::PrintPersonInfo(){ int i; cout<<"身份证号:"< if(Sex==man)cout<<"男"<<'\n'; else if(Sex==woman)cout<<"女"<<'\n'; else cout<<" "<<'\n'; cout<<"出生年月日:"; i=Birthday; cout< i=i%10000; cout< void main(){ Person Ps1("320102*********","朱海鹏",man,19811226,"南京市黄浦路1号 "),Ps2(Ps1),Ps3; Ps1.PrintPersonInfo(); Ps2.PrintPersonInfo(); Ps3.inputPerson(); Ps3.PrintPersonInfo(); } 5.8 为复数类(Complex)增加重载的运算符-、-=、*=和/=。设++为实部和虚部各自增一, 亦请重载前置与后置++运算符。分别使用成员函数和友元函数各做一遍。并测试。解:注意后++,返回的是原值,但实部和虚部已各自增一,所以要先保留原值,再++。这里是使用成员函数。 #include class complex{ private: double real; //实部 double imag; //虚部 public: complex(double r = 0.0 ,double i = 0.0 ); //构造函数 void print(); //显示复数 complex operator +(complex c); //重载复数"+" complex operator -(complex c); //重载复数"-" complex operator *(complex c); //重载复数"*" complex operator /(complex c); //重载复数"/" complex operator +=(complex c); //重载复数"+=" complex operator -=(complex c); //重载复数"-=" complex operator *=(complex c); //重载复数"*=" complex operator /=(complex c); //重载复数"/=" complex operator ++(); //重载复数前缀"++" complex operator ++(int); //重载复数后缀"++" }; complex::complex(double r,double i){ real = r; imag = i; } complex complex::operator +(complex c){ //重载复数"+" complex temp; temp.real = real + c.real; temp.imag = imag + c.imag; return temp; } complex complex::operator -(complex c){ //重载复数"-" complex temp; temp.real = real - c.real; temp.imag = imag - c.imag; return temp; } complex complex::operator *(complex c){ //重载复数"*" complex temp; temp.real = real * c.real - imag * c.imag; temp.imag = real * c.imag + imag * c.real; return temp; } complex complex::operator /(complex c){ //重载复数"/" complex temp; double d; d = (c.real*c.real + c.imag*c.imag); temp.real = (real * c.real + imag * c.imag)/d; temp.imag = (c.real * imag - real * c.imag)/d; return temp; } complex complex::operator +=(complex c){ //重载复数"+=" real = real + c.real; imag = imag + c.imag; return *this; } complex complex::operator -=(complex c){ //重载复数"-=" real = real - c.real; imag = imag - c.imag; return *this; } complex complex::operator *=(complex c){ //重载复数"*=" complex temp; temp.real = real * c.real - imag * c.imag; temp.imag = real * c.imag + imag * c.real; *this = temp; return *this; } complex complex::operator /=(complex c){ //重载复数"/=" complex temp; double d; d = (c.real*c.real + c.imag*c.imag); temp.real = (real * c.real + imag * c.imag)/d; temp.imag = (c.real * imag - real * c.imag)/d; *this = temp; return *this; } complex complex::operator ++(){ //重载复数前缀"++" ++this->real;//完整表达形式 ++this->imag; return *this; } complex complex::operator ++(int){ //重载复数后缀"++" complex temp(real,imag); real++; imag++; return temp; } void complex::print(){ //显示复数cout << real; if(imag > 0) cout << "+"; if(imag != 0) cout << imag << "i" << endl; } void main(){ complex A(30,40),B(15,30),C; //定义3个复数对象 cout<<"A为:"; A.print(); C=A.operator++(1);//即A++ cout<<"C=A++后,C为:"; C.print(); cout<<"A为:"; A.print(); C=A.operator++();//即++A cout<<"C=++A后,C为:"; C.print(); cout<<"A为:"; A.print(); cout<<"B为:"; B.print(); C=A+B; cout<<"C=A+B后,C为:"; C.print(); A+=B; cout<<"A+=B后,A为: "; A.print(); C=A-B; cout<<"C=A-B后,C为:"; C.print(); A-=B; cout<<"A-=B后,A为: "; A.print(); C=A*B; cout<<"C=A*B后,C为:"; C.print(); A*=B; cout<<"A*=B后,A为: "; A.print(); C=A/B; cout<<"C=A/B后,C为:"; C.print(); A/=B; cout<<"A/=B后,A为: "; A.print(); cout< }