C++面向对象程序设计教程课后题答案
什么是面向对象程序设计
面向对象程序设计是一种新的程序设计范型.这种范型的主要特征是:
程序=对象+消息
面向对象程序的基本元素是对象。
主要结构特点是:
第一, 程序一般由类的定义和类的使用两部分组成;
第二, 程序中的一切操作都是通过向对象发送消息来实现的。
什么是对象什么是类对象与类之间的关系是什么
对象是描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体。
类就是具有相同的数据和相同的操作的一组对象的集合,也就是说,类是对具有相同数据结构和相同操作的一类对象的描述。
类和对象之间的关系是抽象和具体的关系。类是多个对象进行综合抽象的结果,一个对象是类的一个实例。
现实世界中的对象有哪些特征请举例说明。
现实世界中的对象具有以下特征:
1) 每一个对象必须有一个名字以区别于其他对象;
2) 用属性来描述对象的某些特征;
3) 有一组操作,每组操作决定对象的一种行为;
4) 对象的行为可以分为两类:一类是作用于自身的行为,另一类是作用于其他对象的行为。
例如一个教师是一个对象。每个教师对象有自己的名字来和别的教师区别。教师具有编号,姓名,年龄,职称,专业等属性。教师拥有走路,吃饭,授课等行为操作。走路,吃饭是作用于自身的行为,授课是作用于其他对象的行为。
什么是消息消息具有什么性质
一个对象向另一个对象发出的请求成为“消息”。
消息具有以下3个性质:
1) 同一个对象可以接收不同形式的多个消息,做出不同的相应;
2) 相同形式的消息可以传递给不同的对象,所做出的响应可以是不同的;
3) 对消息的响应并不是必须的,对象可以响应消息,也可以不响应。
什么是抽象和封装请举例说明。
抽象是将有关事物的共性归纳、集中的过程。
例如:把所有具有大学生学籍的人归为一类,成为“大学生”,这就是一个抽象。
封装是指把数据和实现操作的代码集中起来放在对象内部,并尽可能隐藏对象的内部细节。
例如:每一台洗衣机都有出厂日期、机器编号等属性,也有启动、暂停、选择等操作。人们在使用洗衣机的时候只需要按下对应的按钮,而不用关心具体的内部实现。这就是封装。
什么是继承请举例说明。
继承就是允许派生类使用基类的数据和操作,同时,派生类还可以增加新的操作和数据。
例如:哺乳动物是一种热血、有毛发、用奶哺育幼崽的动物; 狗是有犬牙、食肉、特定的骨骼结构、群居的哺乳动物。 狗就继承了哺乳动物。
若类之间具有继承关系,则他们之间具有什么特征
若类之间具有继承关系,则他们之间具有下列几个特征:
1) 类间具有共享特征(包括数据和操作代码的共享);
2) 类间具有差别或新增部分(包括非共享的数据和操作代码);
3) 类具有层次结构。
什么是单继承、多继承请举例说明。
单继承是指每个派生类只直接继承了一个基类的特征。例如狗继承自哺乳动物。
多继承是指多个基类派生出一个派生类的继承关系。比如玩具车同时继承自玩具和车。
什么是多态请举例说明。
多态是指不同的对象收到相同的消息时执行不同的操作。
例如,有一个窗口类对象,还有一个棋子类对象。当我们发出“移动”消息时,两个对象的行为不同。
面向对象程序设计的主要优点是什么
1. 可提高程序的重用性;
2. 可控制程序的复杂性;
3. 可改善程序的可维护性;
4. 能够更好地支持大型程序设计;
5. 增强了计算机处理信息的范围;
能够很好地适应新的硬件环境。
简述C++的主要特点。
1) C++是C的超集,保持与C的兼容。
2) 保持了C的简洁、高效和接近汇编语言等特点,并对C的功能作了不少扩充。用C++编写的程序比C更安全,可读性更好,代码结构更为合理。
3) 程序质量高。
4) 增加了面向对象机制。
#include using namespace std; int main() { int a, b, d, min; cout << \"Enter two numbers:\"; cin >> a >> b; min = a > b b : a; for(d = 2; d < min; d++) { if(((a % d) == 0) && ((b % d ) == 0)) break; } if (d == min) { cout << \"No common denominators\" << endl; return 0; } cout << \"The lowest common denominator is\" << d << endl; return 0; } 有效 没有函数声明; 函数定义没有写返回值类型。 (1)等价,函数声明可以省略参数的名字。 (2)不等价,第二个的函数定义不能省略参数的名字。 CDAAB ACBDC DC 101 10 10 10 20 举例说明可以使用const替代#define以消除#define的不安全性。 #include using namespace std; int main() { int a = 1; #define T1 a+a #define T2 T1-T1 cout << \"T2 is \" << T2 < } 上面这个程序,初看应该输出 T2 is 0 但是实际上,得出T2 is 2 如果把#define换成const, 则可以输出想要的结果。 用动态分配空间的方法,计算Fibonacci数列的前20项,并存储到动态分配的空间中。 #include using namespace std; int main() { int *pi = new int[20]; *pi = 1; pi[1] = 1; for(int i = 2; i < 20; i++) { pi[i] = pi[i - 2] + pi[i - 1]; } return 0; } 重载sroot函数,输出一个数的二次方根。 #include using namespace std; double sroot(int num) { return (double)sqrt((double)num); } double sroot(long num) { return (double)sqrt((double)num); } double sroot (double num) { return (double)sqrt(num); } int main() { return 0; } 解决百钱问题。将一元人民币换成1、2、#include using namespace std; int main() 分的硬币,有多少种换法 5 { int num = 0; Default constructor called. Default constructor called. Construcotor:a=1,b=2 Construcotor:a=3,b=4 Construcotor:a=5,b=6 Con. Copy con. default. Copy con. A=5 B=14 A=9 B=14 5,7 Constructing Constructing A=5 B=15 A=10 B=15 Destructing Destructing void pintStu();函数只有声明,没有定义。 age是私有成员,不能用对象直接调用。 void printStu() 和 void setSno(int s) 没有加限定符 Student:: void setAge(int a)在类中没有声明 构造函数不能定义为私有。否则无法创建对象。 下面是一个计算器类的定义,请完成该类成员函数的实现。 class counter { public: counter(int number); void increment(); ult() << \" \"; } } 修改,通过对象指针访问对象数组,使程序以相反的顺序显示每个对象数组元素的qu*price值。 class book { private: int qu, price; public: book(int qu); int mult(); }; book::book(int q) { if(q < 1 || q > 5) { qu = 1; } else { qu = q; } price = 10 * qu; } int book::mult() { return qu * price; } int main() { book books[5] = {1,2,3,4,5}; book *p = books; p += 4; for(int i = 0; i < 5; i++) { cout << p->mult() << \" \"; --p; } return 0; } 构建一个类Stock,含字符数组stockcode[]及整型数组成员quan、双精度型数据成员price。构造函数含3个参数:字符数组na[]及q、p。当定义Stock的类对象时,将对象的第一个字符串参数赋给数据成员stockcode,第2和第3个参数分别赋给quan、price。未设置第2和第3个参数时,quan的值为1000,price的值为.成员函数print没有形参,需使用this指针,显示对象数据成员的内容。编写程序显示对象数据成员的值。 #include using namespace std; class Stock { private: char stockcode[25]; int quan; double price; public: Stock(char na[], int q = 1000, double p = ; Stock(char na[]); void print(); }; Stock::Stock(char na[], int q = 1000, double p = { strcpy(stockcode, na); quan = q; price = p; } void Stock::print() { cout << \"stockcode: \" << this->stockcode << \" quan: \" << this->quan << \" price: \" << this->price << endl; } int main() { Stock stock1(\"600001\", 3000, ; Stock stock2(\"600002\"); (); (); return 0; } 编写一个程序,已有若干学生的数据,包括学号、姓名、成绩,要求输出这些学生的数据并计算出学生人数和平均成绩(要求将学生人数和总成绩用静态数据成员表示)。 #include using namespace std; class student { private: char name[25], studentNo[10]; int score; static int sum; static int totalScore; public: student(char na[], char stuNo[], int sc); void show(); static void showTotal(); }; student::student(char na[], char stuNo[], int sc) { strcpy(name, na); strcpy(studentNo, stuNo); score = sc; ++sum; totalScore += sc; } void student::show() { cout << \"姓名: \" << name < cout << \"成绩: \" << score << endl; } void student::showTotal() { cout << \"总人数: \" << sum << endl; cout << \"平均成绩: \" << (double)totalScore/sum < int student::sum = 0; int student::totalScore = 0; int main() { student s1(\"张无忌\", \"111254\", 75); student s2(\"李莫愁\", \"254114\", 60); student s3(\"小龙女\", \"112587\", 88); (); (); (); student::showTotal(); return 0; } 有哪几种继承方式每种方式的派生类对基类成员的继承性如何 公有继承,私有继承和保护继承。 基类的私有成员,无论哪种继承方式都不能访问。 公有继承不改变基类的公有和保护成员的访问限制。 私有继承将基类的公有和保护成员都变成私有。 保护继承将基类的公有和保护成员都变成保护。 派生类能否直接访问基类的私有成员若否,应如何实现 不能。可以在基类里添加一个公有成员函数来访问私有成员,派生类就能继承这个公有成员函数,实现对基类私有成员的访问。 保护成员有哪些特性保护成员以公有方式或私有方式继承后的访问特性如何 保护成员只能被本类或本类的派生类所访问,在类或派生类外是不能被访问的。 后面一问见第一题的答案。 派生类构造函数和析构函数的执行顺序是怎样的 构造函数是先执行父类的构造函数,再执行类中其他类对象的构造函数,再执行本类的构造函数。如果同级有多个构造函数,则按声明顺序执行。 析构函数与构造函数的执行顺序刚好相反。 派生类构造函数和析构函数的构造规则是怎样的 派生类名(参数总表) : 基类名(参数总表) { 派生类新增数据成员的初始化语句 } 派生类中的析构函数与基类无关。 什么是多继承多继承时,构造函数与析构函数的执行顺序是怎样的 多继承是指一个类同时继承自多个不同的基类。 执行顺序同 在类的派生中为何要引入虚基类虚基类构造函数的调用顺序是如何规定的 如果一个类有多个直接基类,而这些直接基类又有一个共同的基类,则在最底层的派生类中会保留这个简介的共同基类数据成员的多份同名成员。在访问这些同名成员的时候,会产生二义性。为了解决二义性,引入了虚基类。 1) 如果虚基类中定义有带形参的构造函数,并且没有定义默认形式的构造函数,则整个继承结构中,所有直接或间接的派生类都必须在构造函数的成员初始化表中列出对虚基 类构造函数的调用,以初始化在虚基类中定义的数据成员。 2) 建立一个对象时,如果这个对象中含有从虚基类继承来的成员,则虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。该派生类的其他基类对虚基类构造函数的调用都自动被忽略。 3) 若同一层次中同时包含虚基类和非虚基类,应先调用虚基类的构造函数,再调用非虚基类的构造函数,最后调用派生类的构造函数。 ACCB Constructor B1. Constructor B2. Constructor A. 3 2 1 主食=bread 副食=steak 0,0,0 0,1,0 3,6,9 Constructor B1. Constructor B2. Constructor B3. Constructor A. 1 2 4,3 4 (1,2) 5,6 (6,9) class base1 class base2 class level2 class base2 class level1 class toplevel #include using namespace std; #include class table { public: table(int p, int q) { i = p; j = q; } void ascii(void); protected: int i, j; }; void table::ascii() { int k = 1; for(; i <= j; i++) { cout << setw(4) << i << \" \" << (char)i; if((k)%12 == 0) { cout << \"\\n\"; } k++; } cout << \"\\n\"; } class der_table:public table { public: der_table(int p, int q, char *m):table(p,q) { c = m; } void print(); protected: char *c; }; void der_table::print() { cout << c <<\"\\n\"; table::ascii(); } int main() { der_table ob('a', 'z', \"ASCII value---char\"); (); return 0; } #include using namespace std; #include class area_c1 { protected: double height; double width; public: area_c1(double r, double s) { height = r; width = s; } virtual double area() = 0; }; class rectangle : public area_c1 { public: rectangle(double r, double s):area_c1(r, s){} virtual double area(); }; double rectangle::area() { return height * width; } class isosceles : public area_c1 { public: isosceles(double r, double s):area_c1(r, s){} virtual double area(); }; double isosceles::area() { return (height * width)/2; } int main() { rectangle r(10, 5); isosceles i(4, 6); area_c1 *a; a = &r; cout<< \"矩形的面积是:\" << a->area() << endl; a = &i; cout << \"三角形的面积是:\" << a->area() < } #include using namespace std; #include class Time { public: Time(int h, int m, int s) { hours = h; minutes = m; seconds = s; } void display() { cout << \"出生时间:\" << hours << \"时\" << minutes << \"分\" << seconds << \"秒\" << endl; } protected: int hours, minutes, seconds; }; class Date { public: Date(int m, int d, int y) { month = m; day = d; year = y; } void display() { cout << \"出生年月:\" << year << \"年\" << month << \"月\" << day << \"日\" << endl; } protected: int month, day, year; }; class Birthtime : public Time, public Date { public: Birthtime(char name[], int m, int d, int y, int h, int mi, int s): Time(h, mi, s), Date(m, d, y) { strcpy(Childname, name); } void showName() { cout << \"我的名字是: \" << Childname << endl; } private: char Childname[25]; }; int main() { Birthtime b(\"xiaoming\", 3, 6, 2012, 11, 12, 42); (); ::display(); ::display(); return 0; } #include using namespace std; #include class person { protected: char number[25]; char name[25]; public: person(char num[], char na[]) { strcpy(number, num); strcpy(name, na); } void showName() { cout << \"编号:\" << number << \" 姓名:\" << name; } }; class student : public person { private: int classNumber, score; public: student(char num[], char na[], int cNumber, int sc):person(num, na) { classNumber = cNumber; score = sc; } void show() { showName(); cout << \" 班号:\" << classNumber << \" 成绩:\" << score << endl; } }; class teacher : public person { private: char title[25], department[25]; public: teacher(char num[], char na[], char tit[], char depart[]):person(num, na) { strcpy(title, tit); strcpy(department, depart); } void show() { showName(); cout << \" 职称:\" << title << \" 部门:\" << department << endl; } } C++第五章习题 1. 什么是静态联编什么是动态联编 静态联编是指系统在编译时就决定如何实现某一动作。 动态联编是指系统在运行时动态实现某一动作。 1. 编译时的多态性与运行时的多态性有什么区别他们的实现方式有什么不同 静态联编支持的多态性称为编译时多态性,也称静态多态性。编译时多态性是通过函数重载和模板实现的。 动态联编所支持的多态性称为运行时多态性,也称动态多态性。是通过虚函数来实现的。 1. 简述运算符重载规则。 a) C++中绝大部分的运算符允许重载。 b) C++只能对已有的C++运算符进行重载。 c) 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造完成。应与原有的功能相类似。 d) 重载不能改变运算符的操作对象的个数。 e) 重载不能改变运算符原有的优先级。 f) 不能改变原有的结合特性。 g) 参数至少应有一个是类对象。 h) 重载函数可以是普通函数,也可以是类的成员函数,也可以是类的友元函数。 i) 一般用于类对象的运算符除了赋值运算符都要重载。 1. 友元运算符函数和成员运算符函数有什么不同 a) 对于双目运算符,成员运算符重载含有一个参数,友元重载含有两个参数;对于单目运算符,成员重载没有参数,友元重载有一个参数。 b) 双目运算符一般可以被重载为友元或成员。但是如果将一个对象和一个普通类型运算,必须重载为友元。 c) 调用方式不同。 d) 一般,双目运算符用友元,单目运算符用成员。如果操作数有隐式类型转换,则必须用友元。 1. 什么是虚函数虚函数与函数重载有哪些相同点与不同点 虚函数就是在基类中被关键字virtual说明,并在派生类中重新定义的函数。 函数名都相同。 重载函数的参数个数或参数类型必须有所不同。虚函数要求函数名,返回类型,参数个数,参数的类型和顺序与基类中的虚函数原型完全相同。 1. 什么是纯虚函数什么是抽象类 纯虚函数是一个在基类中说明的虚函数,它在该基类中没有定义,但要求在它的派生类中根据需要对它进行定义,或仍说明为纯虚函数。 如果一个类至少有一个纯虚函数,那么就称这个类为抽象类。 7-12 DAADCC 13. 不对,参数个数必须一样。 14. 7 6 15. This is c++book. 第一个字符:T 第16个字符:. 第26个字符:数组下标超界! 16. m=千米 17. #include using namespace std; class twoDArray { int a[2][3]; public: twoDArray() { for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) a[i][j] = 5; } twoDArray(int b[][3]) { for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) a[i][j] = b[i][j]; } void show(); twoDArray operator+(twoDArray n); twoDArray operator-(twoDArray n); }; void twoDArray::show() { for(int i = 0; i <2; i ++) { for(int j = 0; j < 3; j ++) cout << a[i][j]; cout << endl; } } twoDArray twoDArray::operator+(twoDArray n) { twoDArray temp; for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) [i][j] = a[i][j] + [i][j]; return temp; } twoDArray twoDArray::operator-(twoDArray n) { twoDArray temp; for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) [i][j] = a[i][j] - [i][j]; return temp; } int main() { int a[2][3]; for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) cin >> a[i][j]; twoDArray a1, a2(a), total, sub; total = a1 + a2; sub = a1 - a2; (); (); return 0; } 18. #include using namespace std; class twoDArray { int a[2][3]; public: twoDArray() { for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) a[i][j] = 5; } twoDArray(int b[][3]) { for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) a[i][j] = b[i][j]; } void show(); friend twoDArray operator+(twoDArray m, twoDArray n); friend twoDArray operator-(twoDArray m, twoDArray n); }; void twoDArray::show() { for(int i = 0; i <2; i ++) { for(int j = 0; j < 3; j ++) cout << a[i][j]; cout << endl; } } twoDArray operator+(twoDArray m, twoDArray n) { twoDArray temp; for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) [i][j] = [i][j] + [i][j]; return temp; } twoDArray operator-(twoDArray m, twoDArray n) { twoDArray temp; for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) [i][j] = [i][j] - [i][j]; return temp; } int main() { int a[2][3]; for(int i = 0; i <2; i ++) for(int j = 0; j < 3; j ++) cin >> a[i][j]; twoDArray a1, a2(a), total, sub; total = a1 + a2; sub = a1 - a2; (); (); return 0; } 19. #include using namespace std; class complex { double real, imag; public: complex(double re, double im) { real = re; imag = im; } friend complex operator+(complex a, complex b); void print(); }; complex operator+(complex a, complex b) { return complex + , + ; } void complex::print() { cout << \"(\" << real << \ << imag << \")\" << endl; } int main() { complex c1,; complex c2,; complex total = c1 + c2; (); return 0; } 20. #include using namespace std; const double PI = ; class Container { protected: double r, d; 如果是圆柱体,r为底面半径,d为高。如果是正方体,r为边长, d为0。 public: Container(double a, double b = 0) { r = a; d = b; } virtual double serface() = 0; cerr和clog间的区别是 cerr不经过缓冲区直接显示错误信息。而clog存放在缓冲区,缓冲区满或遇上endl时再输出。 C++提供哪两种控制输入输出格式的方法 一种是使用ios类中的有关格式控制的流成员函数进行格式控制,另一种是使用称为操纵符的特殊类型的函数控制。 C++进行文件输入输出的基本过程是什么 首先创建一个流对象,然后将这个流对象与文件相关联,即打开文件,此时才能进行读写操作,读写操作完成后再关闭这个文件。 BCA #include #include using namespace std; int factorial(int n) { if(n == 0 || n == 1) return n; return factorial(n-1)*n; } int main() { for(int i = 1; i <= 9; i++) { cout << setw(5) << factorial(i); if(i % 3 == 0) { cout << endl; } } return 0; } #include #include using namespace std; int main() { for(int i = 1; i <= 7; i++) { cout << setw(16-i); for(int j = 1; j <= (2*i - 1); j++) { cout << 'A'; } cout << endl; } return 0; } #include #include using namespace std; class matrix { private: int data[2][3]; public: matrix(){} friend ostream &operator<<(ostream &, matrix &); friend istream &operator>>(istream &, matrix &); friend matrix operator+(matrix &, matrix &); }; ostream &operator<<(ostream &os, matrix &a) { for(int i = 0; i < 2; i++) { for(int j = 0; j < 3; j++) { os << [i][j] << \" \"; } os << endl; } return os; } istream &operator>>(istream &in, matrix &a) { cout << \"请输入一个2行3列矩阵:\" << endl; for(int i = 0; i < 2; i++) { for(int j = 0; j < 3; j++) { in >> [i][j]; } } return in; } matrix operator+(matrix &a, matrix &b) { matrix temp; for(int i = 0; i < 2; i++) { for(int j = 0; j < 3; j++) { [i][j] = [i][j] + [i][j]; } } return temp; } int main() { matrix m1, m2, total; cin >> m1 >> m2; total = m1 + m2; cout << total; return 0; } #include #include using namespace std; int main() { fstream fout(\"\",ios::out); if(!fout) { cout << \"文件打开失败!\" << endl; return 1; } fout << \"Shen fa zhan 000001\\n\"; fout << \"shang hai qi che 600104\\n\"; fout << \"Guang ju neng yuan 000096\"; (); return 0; } #include #include using namespace std; int main() { char str[30]; fstream in(\"\", ios::in); if(!in) { cout << \"打开文件错误!\\n\"; abort(); } in >> str >> str; for(int i = 0; i < 30; i++) { if(str[i] != 0 && (str[i] < 'A')) { str[i] += ('A' - 'a'); } } fstream out(\"\", ios::out); if(!out) { cout << \"打开文件失败!\\n\"; abort(); } out >> str; (); (); return 0; } #include #include using namespace std; int main() { char str[30]; fstream in(\"\", ios::in); if(!in) { cout << \"打开文件错误!\\n\"; abort(); } in >> str >> str; for(int i = 0; i < 30; i++) { if(str[i] != 0 && (str[i] < 'A')) { str[i] += ('A' - 'a'); } } fstream out(\"\", ios::app); if(!out) { cout << \"打开文件失败!\\n\"; abort(); } out >> str; (); (); return 0; } 不会。 #include #include \"\" #include \"\" using namespace std; class order { private: int orderID; int buyerID; int listcount; string orderlist[20]; static int ordercount; public: order(buyer &person, book &b[], int bookNumber) { ordercount++; orderID = ordercount; buyerID = ; listcount = bookNumber; for(int i = 0; i < bookNumber; i++) orderlist[i] = b[i].book_ID; } void show() { cout << \"订单编号: \" << orderID << \"\\n购书人编号: \" << buyerID << \"\\n购书数量: \" << listcount << endl; for(int i = 0; i < listcount; i++) cout << \"书号: \" << orderlist[i] << endl;; } }; int order::ordercount = 0; int main() { book *c[20]; book c1(\"7-302-0145214-6\", \"C程序设计\", \"谭浩强\", \"清华\", 25); book c2(\"7-302-0145214-7\", \"C++程序设计\", \"谭浩强\", \"清华\", 28); c[1] = &c1; c[2] = &c2; layfolk b1(\"林晓茶\", 1, \"北京\", 0); order ord(b1, c, 2); (); return 0; } 因篇幅问题不能全部显示,请点此查看更多更全内容