2008-2009学年第1学期
2007级《C++面向对象程序设计》期末考试试题(A卷)
考试时间:2009年1月16日
班级 学号 姓名 ? 本试卷满分100分;
? 请将答案写在答题纸上,写明题号,不必抄题,字迹工整、清晰;
? 请在答题纸和试题纸上都写上你的班级,学号和姓名,交卷时请将试题纸、答题纸和草纸
一并交上来。
一、单选题(共20分,每题2分)
1. C++语言对C语言做了很多改进,其中最重要改进是:
(A) 增加了一些新的运算符 (B) 允许函数重载,并允许设置缺省参数 (C) 规定函数说明符必须用原型 (D) 引进了类和对象的概念 2. 下列关于类和对象的描述中,错误的是:
(A) 类就是C语言中的结构体,对象就是C语言中的结构体变量 (B) 类和对象之间的关系是抽象和具体的关系 (C) 对象是类的实例,一个对象必须属于一个类
(D) 类是一组具有相同属性和行为特征的对象的抽象描述 3. 下列关于类的描述中,正确的是:
(A) 类中只能给出成员函数的函数原型,但不能给出其函数体的实现代码 (B) 类中的成员函数可以在类体中实现,也可以在类体之外实现 (C) 类中的成员函数在类体之外实现时必须要与类声明在同一文件中 (D) 在类体之外实现的成员函数函数体内不能访问该类的私有数据成员 4. 下列关于构造函数和析构函数的描述中,正确的是: (A) 一个类有多个构造函数,那么其中一定有一个是无参的构造函数 (B) 构造函数参数表中的参数,要么都有缺省值,要么都没有缺省值
(C) 析构函数可以用const关键字修饰 (D) 析构函数的函数体中,可以访问本类的非静态成员,但不应访问基类中的非静态成员 5. 下列对静态成员的描述中,正确的是:
(A)静态成员数据是类的所有对象共享的数据 (B) 类的每个对象都有自己的静态成员数据 (C)类的不同对象有不同的静态成员数据值 (D) 静态成员函数不能通过类的对象调用 6. 下列语句,正确的是:
(A) long* const cplVar; (B) const long lcVar; (C) const long* const cplcVar; (D) const long* plcVar; 7. 下列关于内联函数的描述中,正确的是:
(A) 内联函数在运行时是将该函数的目标代码插入每个调用该函数的地方 (B) 使用内联函数的目的之一提高程序的执行速度 (C) 内联函数必须在类体内实现
(D) 内联函数只能在类体外实现,而且必须添加关键字inline
第 1 页 共 4 页
8. 下列关于基类和派生类的描述中,错误的是: (A) 一个派生类可以作为另一个派生类的基类
(B) 派生类至少有一个基类 (C) 派生类只继承了基类的公有成员和保护成员
(D) 派生类的继承方式可以是公有的、保护的或私有的
9. 在公有继承的情况下,下列关于派生类对象和基类对象的关系的描述中,错误的是:
(A) 派生类的对象可以直接访问基类成员 (B)派生类对象可以初始化基类的引用型变量 (C) 派生类的对象可以赋给基类的对象 (D)派生类对象的地址可以赋给指向基类的指针 10. 下列关于虚函数的描述中,正确的是:
(A) 虚函数是static类型的成员函数 (B) 虚函数可以不是成员函数
(C) 基类中声明了虚函数后,派生类中与其对应的函数可不必声明为虚函数 (D) 含有虚函数的类一定是抽象类
二、判断正误,对于你认为错误的论述,说明原因或举出反例。(共20分,每题2分) 1. 构造函数可以重载,析构函数也可以重载。 2. 假定A为一个类,已定义A类的对象a,则执行A b=a; 语句时将自动调用该类的赋值函数。 3. 静态成员函数能访问静态成员,还可以访问常成员数据。
4. 在非const成员函数中,this的类型是一个指向类类型的const指针,可以改变this所指向
的对象的值,但不能改变this所保存的地址值。
5. 类Outer中有嵌套类Inner,那么sizeof(Outer)的值大于等于sizeof(Inner)的值。 6. 没有任何数据成员的类不能被实例化。
7. 已知类A是类B的友元,类B是类C的友元,则类A一定是类C的友元。
8. 已知类B以私有方式继承类A,那么类C无论以何种方式继承类B,在类C的成员函数函
数体内,都不能直接访问类A的成员。
9. 执行普通成员函数时,可能产生异常;但执行构造函数时,不会产生异常。
10. 一个基类中声明了纯虚函数,则该类是抽象类,其纯虚函数的实现由派生类给出,并且派
生类一定不再是抽象类。
三、指出下列程序代码片断中存在的不合理之处,并简要说明理由。(共10分,每题2分) 1. const char* pc= \ *pc=\3. class MyRef { int& ri; public: MyRef( int ii ){ri=ii}; } 2. int & ref; 4. class AbstractObject { public: ~AbstractObject( ); virtual void doit( ) = 0; }; 5. class A { public:A(int n):val(n) {} private: int val; }; void main( ) { A * ps = new A[3](1,2,3); delete[ ] ps; } 四、回答下列各题(每题4分,共20分) 1. 举例说明函数重载的不同判定依据 (至少3种)。
2. 请说明语句块try {} catch(Exception& e) { } 和try {} catch(…) { } 在语义上的区别。 3. 既然编译器可以提供缺省的拷贝构造函数,为什么有时还要自定义拷贝构造函数?
第 2 页 共 4 页
4. 对于无继承关系的两个类A和B, 并有函数void f(B)。请举例说明,如何才能让语句块
A a; f(a); 编译通过并执行(至少两种方式)。 5. 举例说明虚的析构函数的作用。
五、按要求用文字描述一个实际问题。 (5分) 表1 class A { public:virtual ~A( ); bool f(A &); }; class B:pubic A { public: virtual ~B( ); }; class C:public A { public: virtual ~C( ); }; 针对实际问题—“游戏中有多种怪物,如猫、狗等,每个怪物都可能与其它怪物发生战斗。”进行面向对象程序设计时, 可以抽象出怪物、猫、狗三个类,而且这些类及其成员函数与表1中的代码具有一致的对应关系:怪物对应类A,猫对应类B,狗对应类C,战斗对应于成员函数f,等等。因此,我们可以说“游戏中有多种怪物,?”这个实际问题是对应于表1代码的一个应用例子。 表2 class D { }; class A { public: virtual ~A( ); virtual void f(D&) = 0; }; class B:pubic A { public: virtual ~B( ); virtual void f(D &); }; class C:public A { public: virtual ~C( ); virtual void f(D&); }; 现请你使用文字也描述一个实际问题,使得该问题是对应于表2代码的一个应用例子。 六、分别写出下面两个程序的运行结果(共10分,每题5分) 1. #include
(Employee),雇员又分为经理(Manager)、普通员工(Stuff)等,每个雇员有各自不同的月工资;各部门有年度总利润,部门人均奖金基数为该部门年度总利润的30%再除以部门人数;将来雇员的种类可能会增加,具体的奖金计算规则也可能有变化,但雇员的年度奖金肯定与部门人均奖金基数相关。目前,奖金计算规则为:
经理的年度奖金额 = 本人月工资 * 2 + 部门人均奖金基数 * 2; 普通员工的年度奖金额 = 本人月工资 + 部门人均奖金基数 * 0.8。
为了测试设计的合理性,在假定每个部门有且只有3人的情况下,该同学编写了下面一段
代码。
class Department {
public: Department(long totalprofit): profit(totalprofit)
{ emps[0]=emps[1]=emps[2]=0; }
void SetEmployee(Employee * aEmp,int index) {emps[index] = aEmp; } void ShowEveryAward( )
{ for(int i=0;i<3;++i) cout< 1)请根据上面代码,增加必要的类,给出类的具体实现,以帮助该同学完成设计工作。 2)在如下假定下,写出测试用的main函数代码 某部门共有三人:一个经理,月工资为8000元;两个普通员工,月工资分别为5000元、4000元。该部门的年度总利润为300000元。 (全卷完) 第 4 页 共 4 页