【C++习题笔记】谭浩强C++程序设计(第三版)第九章

本文是谭浩强老师C++程序设计第三版第九章的习题笔记,主要设计类和对象的应用。

1. 构造函数和析构函数的作用是什么?什么时候需要自己定义构造函数和析构函数?

(1)构造函数:是一种特殊的成员函数,它来实现对象的初始化,它不光可以对数据成员进行赋值,还可以包含其他语句,如cout语句等。构造函数可以自己定义也可以由系统默认给出,当用户未定义构造函数时,系统会提供构造函数,只是该函数是空的,不起初始化作用;如果用户希望在建立对象时就能使用成员初值,就必须自己定义构造函数。

(2)析构函数:是与构造函数作用相反的函数,其作用并不是删除对象,二是在撤销对象占用存储空间之前完成一些清理工作,如释放资源,同时还可以用来执行“用户希望在最后一次使用对象之后所执行的任何操作”,如输出相关信息等。一般情况下,类的设计者应该在声明类的同时定义析构函数,以指定如何完成清理工作,若用户没有定义析构函数,系统也会自动生成,但是它只是徒有析构函数的名称和形式,其实什么操作都不执行,要想让析构函数完成任何工作,都需要在定义的析构函数中指定。

2. 分析下面的程序 写出其运行时的输出结果

#include 
using namespace std;
class Date
 {public:
   Date(int,int,int);
   Date(int,int);
   Date(int);
   Date();
   void display();
  private:
   int month;
   int day;
   int year;
 };
 
Date::Date(int m,int d,int y):month(m),day(d),year(y)
 { }
 
Date::Date(int m,int d):month(m),day(d)
 {year=2005;}
 
Date::Date(int m):month(m)
 {day=1;
  year=2005;
 }
 
Date::Date()
 {month=1;
  day=1;
  year=2005;
 }

void Date::display()
 {cout<

分析方法:这是构造函数的重载问题,原则是,同名的构造函数具有不同的参数,系统按调用时的参数形式来判断调用的是哪个构造函数,因此,上述程序按照构造函数的形式相同的来赋初值,可以得到下述结果:

10/13/2005
12/30/2005
10/1/2005
1/1/2005

3. 如果将第2题中程序的第5行改为用默认参数,即Date(int=1,int=1,int=2005); 分析程序有无问题。上机编译,分析出错信息,修改程序使之能通过编译。要求保留上面一行给出的构造函数,同时能输出与第2题的程序相同的输出结果。

编译出错,原因是构造函数使用默认参数后就不能再使用重载的构造函数,否则就会出现歧义,函数不知道调用的是谁。

修改方法:删去所有重载部分即可。

#include 
using namespace std;
class Date
 {public:
   Date(int=1,int=1,int=2005);
   //Date(int,int);
   //Date(int);
   //Date();
   void display();
  private:
   int month;
   int day;
   int year;
 };
 
Date::Date(int m,int d,int y):month(m),day(d),year(y)
 { }
 
//Date::Date(int m,int d):month(m),day(d)
// {year=2005;}
// 
//Date::Date(int m):month(m)
// {day=1;
//  year=2005;
// }
// 
//Date::Date()
// {month=1;
//  day=1;
//  year=2005;
// }

void Date::display()
 {cout<

4. 建立一个对象数组,内放5个学生的数据(学号、成绩),用指针指向数组首元素,输出第1,3,5个学生的数据。

//建立一个对象数组,内放5个学生的数据(学号、成绩),用指针指向数组首元素,输出第1,3,5个学生的数据。
#include 
using namespace std;
class Student
{
public:
	Student(int n,float s):num(n),score(s){};
	void display();
private:
	int num;
	float score;
};
void Student::display()
{cout<display();
	return 0;
}

5. 建立一个对象数组,内放5个学生的数据(学号、成绩),设立一个函数max,用指向对象的指针作函数参数,在max函数中找出5个学生中成绩最高者,并输出其学号。

//建立一个对象数组,内放5个学生的数据(学号、成绩),设立一个函数max,用指向对象的指针作函数参数,在max函数中找出5个学生中成绩最高者,并输出其学号。
#include 
using namespace std;
class Student
{
public:
	Student(int n, float s):num(n),score(s){};
	int max(Student *arr);
	int num;
	float score;
};
int Student::max(Student *arr)
{
	float max_score=arr[0].score;
	int k=0;
	for(int i=1;i<5;i++)
		if(arr[i].score>max_score) {max_score=arr[i].score;k=i;}
	return(k);
}
int main()
{
	Student stu[5] ={Student(101,78.5),Student(102,85.5),Student(103,98.5),Student(104,100.0),Student(105,95.5)};
	int k;
	k = stu[5].max(stu);
	cout<

6. 阅读下面程序,分析其执行过程,写出输出结果。

#include 
using namespace std;
class Student
 {public:
   Student(int n,float s):num(n),score(s){}
   void change(int n,float s) {num=n;score=s;}
   void display(){cout<

程序分析:第一次dispay执行的是stud的初始值,即101,78.5,然后经过change函数,将第二次的101,80.5传入了change,因此第二次展示的结构是101,80.5

因此输出结果是:

101 78.5
101 80.5

7. 将第6题的程序分别作以下修改,分析所修改部分的含义以及编译和运行的情况。 
(1) 将main函数第2行改为const Student stud(101,78.5);
(2) 在(1)的基础上修改程序,使之能正常运行,用change函数修改数据成员num和score的值。
(3) 将main函数改为
int main( )
{Student stud(101,78.5);
Student *p=&stud;
p->display( );
p->change(101,80.5);
p->display( );
return 0;
其他部分仍同第6题的程序。
(4) 在(3)的基础上将main函数第3行改为const Student *p=&stud;
(5) 再把main函数第3行改为Student *const p=&stud;

程序分析:

(1)改变是Student变为了常对象,由常对象的性质,它只能调用对象中的常函数而不能调用普通函数,因此display()函数需改为常函数;同时由于在其生命周期内,对象中所有的数据成员不能被修改,因此change函数没有意义,可以去掉。

因此程序修改如下:

#include 
using namespace std;
class Student
 {public:
   Student(int n,float s):num(n),score(s){}
   void change(int n,float s) {num=n;score=s;}
   //void display() {cout<

(2)若一定要修改常对象中的数字成员,除了将其成员函数变为const类型之外,还要将待修改的数据成员声明为mutable类,如 mutable int count; 即可改变常对象中的数据成员,程序修改如下:

#include 
using namespace std;
class Student
 {public:
   Student(int n,float s):num(n),score(s){}
   void change(int n,float s) const{num = n;score = s;}
   //void display() {cout<

(3)第三小题的改法没有问题,是用指针指向对象的过程,程序正常运行,结果如下

101 78.5
101 80.5

(4)第四小题的改法是用了指向常对象的指针变量,对于它而言,只有用指针访问常对象期间它不可以被改变,而不用指针访问则可以被改变,因此修改如下:

#include 
using namespace std;
class Student
 {public:
   Student(int n,float s):num(n),score(s){}
   void change(int n,float s) {num = n;score = s;}
   //void display() {cout<display( );
stud.change(101,80.5);
p->display( );
return 0;
}

(5)第四小题的改法是将p定义为指向对象的常指针,这种情况下,指针的值不可改变,也就是指向不能改变,但是可以改变指向对象的值,在题中,这种修改只是改变了stud的值,而p指向stud的指向始终没变,因此这种情况下程序正常运行,完整代码如下:

#include 
using namespace std;
class Student
 {public:
   Student(int n,float s):num(n),score(s){}
   void change(int n,float s) {num = n;score = s;}
   //void display() {cout<display( );
p ->change(101,80.5);
p->display( );
return 0;
}

8. 修改第6题的程序,增加一个fun函数,改写main函数。在main函数中调用fun函数,在fun函数中调用change和display函数。在fun函数中使用对象的引用(Student &)作为形参。

这个问题考的是对象的应用,也就是用变量的别名来表示它,此时在fun的形参里是对象Student的引用(别名),而在实参里则是类对象,程序如下:

#include 
using namespace std;
class Student
 {public:
   Student(int n,float s):num(n),score(s){}
   void change(int n,float s) {num=n;score=s;}
   void display() {cout<

9. 商店销售某一商品,商店每天公布统一的折扣(discount)。同时允许销售人员在销售时灵活掌握售价(price),在此基础上,对一次购10件以上者,还可以享受9.8折优惠。现已知当天3名销货员的销售情况为:
   销货员号(num)    销货件数(quantity)       销货单价(price)
     101                   5                    23.5
     102                  12                    24.56
     103                 100                    21.5

请编程序,计算出当日此商品的总销售款sum,以及每件商品的平均售价。要求用静态数据成员和静态成员函数。

#include 
using namespace std;
class Product
 {public:
   Product(int n,int q,float p):num(n),quantity(q),price(p){};
   void total();
   static float average();
   static void display();

  private:
   int num;
   int quantity;
   float price;
   static float discount;
   static float sum;
   static int n;
 };

void Product::total()
 {float rate=1.0;
  if(quantity>10) rate=0.98*rate;
  sum=sum+quantity*price*rate*(1-discount);
  n=n+quantity;
 }

void Product::display()
 {cout<

10. 将例9.13程序中的display函数不放在Time类中,而作为类外的普通函数,然后分别在Time和Date类中将display声明为友元函数。在主函数中调用display函数,display函数分别引用Time和Date两个类的对象的私有数据,输出年、月、日和时、分、秒。请读者自己完成并上机调试。

#include 
using namespace std;
class Date;
class Time
 {public:
   Time(int,int,int);
   friend void display(const Date &,const Time &);
  private:
   int hour;
   int minute;
   int sec;
 };
 
 Time::Time(int h,int m,int s)
 {hour=h;
  minute=m;
  sec=s;
 }
 
class Date
 {public:
   Date(int,int,int);
   friend void display(const Date &,const Time &);
  private:
   int month;
   int day;
   int year;
 };
 
Date::Date(int m,int d,int y)
 {month=m;
  day=d;
  year=y;
 }
 
void display(const Date &d,const Time &t)
 {
  cout<

11. 将例9.13中的Time类声明为Date类的友元类,通过Time类中的display函数引用Date类对象的私有数据,输出年、月、日和时、分、秒。

#include 
using namespace std;
class Time;
class Date
 {public:
   Date(int,int,int);
   friend Time;
  private:
   int month;
   int day;
   int year;
 };
 
Date::Date(int m,int d,int y):month(m),day(d),year(y){ }

class Time
 {public:
   Time(int,int,int);
   void display(const Date &);
  private:
   int hour;
   int minute;
   int sec;
 };
 
Time::Time(int h,int m,int s):hour(h),minute(m),sec(s){ }
 
void Time::display(const Date &d)
 {
  cout<

12. 将例9.14改写为在类模板外定义各成员函数。

#include 
using namespace std;
template
class Compare
 {public:
   Compare(numtype a,numtype b);
   numtype max();
   numtype min();
  private:
   numtype x,y;
 };
template 
Compare::Compare(numtype a,numtype b)
  {x=a;y=b;}
template 
numtype Compare::max()
 {return (x>y)?x:y;}
template 
numtype Compare::min()
  {return (x cmp1(3,7);
 cout< cmp2(45.78,93.6);
 cout< cmp3('a','A');
 cout<

 

你可能感兴趣的:(C++学习笔记)