C++OOP复习题-本部(to学生)

更新时间:2024-05-14 06:55:01 阅读量: 综合文库 文档下载

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

C++面向对象程序设计——复习

1. 名词解释

1、 类(Class):人们借助于客观存在的事物的属性和行为认识客观世界,将具

有相同属性和行为的客观对象归为同一类。类是面向对象程序设计的核心,是一种有别于普通数据类型的自定义数据类型。是实现数据封装和信息隐藏的工具,是继承和多态的基础。

2、 对象(Object):参考答案:每类对象都有很多实际存在的个体,这些个体

成为对象。面向对象程序设计中,对象是由类定义出来的变量。类与对象是数据类型与变量的关系,类相当于一种数据类型,对象是用数据类型定义的变量。

3、 抽象(Abstract):是指有意忽略问题的某些细节和与当前目标无关的方面,

以便把问题的本质表达得更清楚。

4、 接口(Interface):程序设计中,对用户可见、用户能够用来完成某项任务的

部分称为接口。

5、 实现(Implementation):程序设计中,那些对用户不可见、具体完成工作任

务的细节称为实现。

6、 封装(Encapsulation):是指将数据抽象的外部接口与内部实现细节分离开

来,将接口显示给用户并允许其访问,将接口的实现细节隐藏起来,不让用户知道,也不允许用户访问。

7、 继承(Inheritance):继承源于生物界,通过继承,后代能够获得与其祖先相

同或相似的特征和能力。面向对象程序设计语言提供了类似于生物继承的语言机制,允许一个新类从现有类派生而来,新类能够继承现有类的属性和行为,并且能够修改或增加新的属性和行为,成为一个功能更强大、更能满足应用需求的类。继承是面向对象程序设计语言模拟生物界后代传承前代的特征和行为的一种机制,其基于一个已有的类创建新类,使新类与已有类具有同样的功能,即新类具有已有类相同的数据成员和成员函数。

8、 多态(Polymorphism):是面向对象程序设计语言的一个重要特征,是指不

同对象收到相同的消息时会执行不同的操作(或产生不同的行为),通俗地说,是指用一个相同的名称定义许多不同的函数,这些函数可以针对不同数据类型实现相同或相似的功能,即所谓的“一个接口多种形态(实现)”。 9、 类型转换:是指将一种数据类型转换为另一种数据类型。可分为隐式类型转

换和显示类型转换。

10、函数重载:是指允许同一作用域内定义多个同名函数,这些同名函数可以有

不同的返回类型、参数类型、参数个数、以及不同的函数功能。

11、引用(Reference):是某个变量(面向对象中则为对象)的别名,即某个对

象的替代名称,相当于变量的第二名称。

12、内联函数():在函数声明或定义时,将inline关键字加在函数返回类型前

面的函数称为内联函数。

13、指针悬挂():在面向对象程序设计中,默认拷贝构造函数以成员按位复制

(bit-by-bit)的方式实现成员的复制。按位复制是指把一个对象的各数据成员的值原样复制到目标对象中。在没有涉及指针类型的数据成员时,默认拷贝构造函数能够很好地工作,但当一个类有指针类型的数据成员时,默认拷贝构造函数常常会产生指针悬挂问题。在没有涉及指针类型的数据成员时,默认拷贝构造函数能够很好地工作,但当一个类有指针类型的数据成员时,默认拷贝构造函数将指针值复制给拷贝对象,使得多个对象的该指针指向同一内存存储区域,删除某个对象将回收该对象内指针所指向的该存储单元,这将导致其它对象内的该指针仍指向先前已经被删除的存储区域,这就是所谓的“指针悬挂”。

14、全局命名空间污染问题:如果在程序中引入一个系统或第三方软件商提供的

库文件,就必须保证程序中定义的全局名(包括变量、函数、类型等的名称)都不能与所用库中的名称相同;如果一个程序由许多程序员共同编写,大家也不能命名相同的全局变量名和函数名,否则将产生名字冲突,这就是所谓的全局命名空间污染问题。

15、作用域:是指标识符在程序中的有效范围。这里的标识符包括变量名、函数

名、常量名、对象名、语句标号、宏名等。

16、生命(周)期:是指标识符在程序中的生存周期,也就是程序运行过程中,

标识符在内存中存在的时间。这里的标识符包括变量名、函数名、常量名、对象名、语句标号、宏名等。

17、构造函数(Constructor):是与类同名的特殊成员函数,主要用来初始化对

象的数据成员。

18、析构函数(Destructor):是与类同名的另一个特殊成员函数,作用与构造函

数相反,用于对象生存期结束时,完成对象的清理工作。

19、友元:C++提供了友元机制,用于允许一个类授权其他函数直接访问类中的

私有(Private)和受保护(Protected)成员。友元包括友元函数、友元类和友元成员函数。

20、重定义:是指面向对象程序设计的继承结构中,派生类可以定义与基类具有

相同函数原型的成员函数,即具有相同的返回类型、函数名及参数列表。而重载则要求成员函数具有不同的函数原型。

21、名字隐藏:是指面向对象程序设计的继承结构中,派生类对基类成员函数的

重定义或重载会影响基类成员函数在派生类中的可见性,基类的同名成员函数会被派生类的同名函数所隐藏。

22、赋值相容:是指在公有派生方式下,凡是需要基类对象的地方都可以使用派

生类对象。即基类对象能够解决的问题,用派生类对象也能够解决,包括三种情况:(a)把派生类对象赋值给基类对象;(b)把派生类对象的地址赋值给基类指针;(c)用派生类对象初始化基类对象的引用。

23、虚拟继承:利用C++提供的关键字virtual限定继承方式,将公共基类指定

为虚基类,以使该基类的成员在派生类中只有一份拷贝,此继承方式称为虚拟继承。

24、绑定(Binding),又称为联编,是指一个源程序需要经过编译、连接才能形

成可执行文件,在这个过程中需要把调用函数名与对应的函数关联在一起,这个过程称为绑定。

25、静态绑定,又称为静态联编,是指在编译程序时就根据调用函数提供的信息,

把它所对应的具体函数确定下来,即在编译程序时就把调用函数名与具体的函数绑定在一起。

26、动态绑定,又称为动态联编,是指在编译程序时还不能确定函数调用所对应

的具体函数,只有在程序运行过程中才能够确定函数调用所对应的具体函数,即在程序运行时才把调用函数名与具体函数绑定在一起。

27、虚函数:由限定词virtual修饰的类成员函数称为虚函数。如果基类中的非

静态成员函数被定义为虚函数,且当派生类重写(重定义)了基类的虚函数,则当通过指向基类对象的指针或引用调用派生类对象中的虚函数时,将会调用到该指针或引用实际所指对象的成员函数。

28、纯虚函数:是指在函数声明时被初始化为0的类成员函数。

29、抽象类:在一个类中可以声明一个或多个纯虚函数,只要有纯虚函数的类称

为抽象类。至少有一个纯虚函数的类称为抽象类。

30、运行时类型信息(RTTI,Run-Time Type Information):提供了在程序运行时

刻确定对象类型的方法,是面向对象程序语言为解决多态问题而引入的一种语言特性。

2. 单选题

1、 C++程序的基本组成单位是( )。 A. 字符 B. 语句

C. 函数

D. 源程序文件

2、 程序运行中需要从键盘上输入多于一个数据时,各数据之间应使用( )

符号作为分隔符。 A. 空格或逗号 B. 逗号或回车 C. 逗号或分号 D. 空格或回车 3、 x>0 && x<=10的相反表达式为( )。 A. x<=0 || x>10 B. x<=0 && x>10 C. x<=0 || x<=10 D. x>0 && x>10

4、 假定指针变量p定义为“int *p=new int(100);”,要释放p所指向的动态内存,

应使用语句( )。

A. delete p; B. delete *p;

C. delete &p; D. delete []p;

5、 函数原型语句正确的是( )。

A. int Function(void a); C. int Function(a);

B.void Function (int);

D.void int(double a);

D. lik

6、 C++源程序文件的缺省扩展名为( )。 A. cpp B. exe C. obj 7、 采用重载函数的目的是( )。 A. 实现共享 C. 提高速度

B. 减少空间

D. 使用方便,提高可读性

8、 面向对象方法的多态性是指( )。 A. 一个类可以派生出多个特殊类 B. 一个对象在不同的运行环境中可以有不同的变体 C. 针对一消息,不同的对象可以以适合自身的方式加以响应 D. 一个对象可以是由多个其他对象组合而成的 9、 在关键字public后面定义的成员为类的( )成员。 A. 私有 B. 公有 C. 保护 10、面向对象软件开发中使用的OOD表示( )。 A. 面向对象分析 B. 面向对象设计 C. 面向对象语言 D. 面向对象方法

11、假定AA为一个类,int a()为该类的成员函数,若该成员函数在类定义体外

定义,则函数头为( )。 A. int AA::a() B. int AA:a() C. AA::a() D. AA::int a() 12、假定AB为一个类,则执行 “AB x(a,5);”语句时将自动调用该类的( )。 A. 带参构造函数 B. 无参构造函数 C. 拷贝构造函数 D. 赋值重载函数 13、设px是指向一个类对象的指针变量,则执行“delete px;”语句时,将自动

调用该类的( )。 A. 无参构造函数 B. 带参构造函数 C. 析构函数 D. 拷贝构造函数 14、假定AB为一个类,则执行“AB a(2), b[3], *p[4];”语句时共调用该类构造

函数的次数为( )。 A. 3 B. 4 C. 5 D. 9 15、当保护继承时,基类的( )在派生类中成为保护成员,在类作用域外不

能够通过派生类的对象来直接访问该成员。 A. 任何成员 B.公有成员和保护成员 C. 保护成员和私有成员 D.私有成员 16、在关键字private后面定义的成员为类的( )成员。 A. 私有 B. 公用 C. 保护

D. 任何 D. 任何

17、对类中常量成员的初始化是通过构造函数中给出的( )实现的。 A. 函数体 B. 参数表 C. 初始化表 D. 初始化表或函数体

18、结构中定义的成员默认为( )访问属性。 A. public B. private C. protected 19、类中定义的成员默认为( )访问属性。 A. public B. private C. protected 20、一个类的构造函数通常被定义为该类的( )成员。 A. 公有 B. 保护 C. 私有

D. friend D. friend D. 友元

21、在多文件结构的程序中,通常把类中所有非内联函数的定义单独存放于

( )中。 A. 主文件 B. 实现文件 C. 库文件 D. 头文件 22、假定AA是一个类,abc是该类的一个成员函数,则参数表中隐含的第一个

参数为( )。 A. abc B. *this C. this D. this& 23、对于一个类的析构函数,其函数名与类名( )。 A. 完全相同 B. 完全不同 C. 只相差一个字符

D. 无关系

24、假定AB为一个类,则执行“AB x;”语句时将自动调用该类的( )。 A. 带参构造函数 B. 无参构造函数 C. 拷贝构造函数 D. 赋值重载函数 25、假定一个类AB只含有一个整型数据成员a,当用户不定义任何构造函数时,

系统为该类定义的无参构造函数为( )。 A. AB() {a=0;} B. AB(int aa=0): a(aa) {} C. AB(int aa): a(aa) {} D. AB() {} 26、假定有“struct BOOK{char title[40]; float price;}book;”,则正确的语句为

( )。 A. BOOK &x= &book; B. BOOK &x=book; C. BOOK &x=new BOOK; D. BOOK &x=BOOK; 27、假定AB为一个类,则执行 “AB a, b(3), *p;”语句时共调用该类构造函数

的次数为( )。 A. 2 B. 3 C. 4 D. 5 28、对类对象成员的初始化是通过构造函数中给出的( )实现的。 A. 函数体 B. 初始化表 C. 参数表 D. 初始化表或函数体 29、一个类的静态数据成员所表示属性( )。 A. 是类的或对象的属性 B. 只是对象的属性 C. 只是类的属性 D. 类和友元的属性

30、当将一个类A或函数f()说明为另一个类B的友元后,类A或函数f()能够

直接访问类B的( )。 A. 只能是公有成员 B. 只能是保护成员 C. 只能是除私有成员之外的任何成员 D. 具有任何权限的成员 31、类的静态成员的访问控制( )。

A. 只允许被定义为private B. 只允许被定义为private或protected

C. 只允许被定义为public D. 可允许被定义为private、protected或public 32、对于公有继承,基类中的私有成员在派生类中将( )。

A. 能够直接使用成员名访问 C. 仍然是基类的私有成员 B. 能够通过成员运算符访问 D. 变为派生类的私有成员

33、从一个基类派生出的各个类的对象之间( )。 A. 共享所有数据成员,每个对象还包含基类的所有属性 B. 共享部分数据成员,每个对象还包含基类的所有属性 C. 不共享任何数据成员,但每个对象还包含基类的所有属性 D. 共享部分数据成员和函数成员 34、类的构造函数是在定义该类的一个( )时被自动调用执行的。 A. 成员函数 B. 数据成员 C. 对象 D. 友元函数 35、引入友元的主要目的是为了( )。 A. 增强数据安全性 C. 提高程序的效率和灵活性

B. 提高程序的可靠性 D. 保证类的封装性

3. 程序填空

1、 面向对象类的构造函数和析构函数定义。

class A { char *a; public:

___(1)___ //定义无参构造函数,使a的值为空 A(char *aa) { a=___(2)___;

strcpy(a,aa); //用aa所指字符串初始化a所指向的动态存储空间 }

___(3)___ //定义析构函数,删除a所指向的动态存储空间 };

答案:

(1) A() {a=0;} 或A():a(0){} (2) new char[strlen(aa)+1] (3) ~A() {delete []a;}

2、 已知一个类的定义如下:

#include class AA { int a[10]; int n; public:

void SetA(int aa[], int nn); //用数组aa初始化数据成员a, //用nn初始化数据成员n int MaxA(); //从数组a中前n个元素中查找最大值

void SortA(); //采用选择排序的方法对数组a中前n个元素 //进行从小到大排序

void InsertA();//采用插入排序的方法对数组a中前n个元素进行从小到大排序 void PrintA(); //依次输出数组a中的前n个元素 //最后输出一个换行

};

使用该类的主函数如下: void main()

{ int a[10]={23,78,46,55,62,76,90,25,38,42}; AA x; ___(1)___;

int m=___(2)___; ___(3)___;

cout<

该程序运行结果为: 23 78 46 55 62 76 78

答案:

(1) x.SetA(a,6) (2) x.MaxA() (3) x.PrintA()

3、 对象实例化与对象指针。

class A { int a,b; public:

A(int aa=0, int bb=0) ___(1)___ {} //分别用aa和bb对应初始化a和b };

void main() {

___(2)___ ; //定义类A的对象x并用8初始化,同时定义y并用x初始化 ___(3)___ ; //定义p指针,使之指向对象x

}

答案:

(1) :a(aa),b(bb) (2) A x(8),y(x) (3) A *p=&x 4、 友元函数

class Point {

private: int x, y; public:

Point(){x=y=0;}

Point(int x0,int y0) {x=x0;y=y0;} int GetX() { return x; } int GetY() { return y; }

void Print(){cout<<\ ___(1)___; //友元函数声明 ___(2)___; //友元函数声明 };

Point operator+(Point& pt,int dd)

//加号操作符重载函数,实现Point类对象与整数加法 {

Point temp=pt; temp.x+=dd; temp.y+=dd; return temp; }

Point operator+(Point& pt1,Point& pt2)

//加号操作符重载函数,实现两个Point类对象的加法 {

Point temp=pt1; temp.x+=pt2.x; ___(3)___; return temp;

} 答案:

(1) friend Point operator+(Point& pt,int dd)

(2) friend Point operator+(Point& pt1,Point& pt2) (3) temp.y+=pt2.y

5、 构造函数与对象的动态创建

class A { int a,b; public:

___(1)___ //定义构造函数,使参数aa和bb的默认值为1, //在函数体中用aa初始化a,用bb初始化b };

main() { A *p1, *p2;

___(2)___ ; //调用无参构造函数生成由p1指向的动态对象 ___(3)___ ; //调用带参构造函数生成由p2指向的动态对象, //使a和b成员分别被初始化为8和9 }

答案:

(1) A(int aa=1, int bb=1){a=aa; b=bb;} (2) p1=new A

(3) p2= new A(8,9)

1、 假设最终派生类E的继承体系结构如图所示。其中,类别B1, B2, D的多重

继承关系的声明按图从左到右的顺序进行,而带阴影的类别A,C,B表示其在继承体系中为虚基类。请根据以下要求进行程序填空: (1)在标有行号L*的地方给出类别B1, B2和E的声明;

(2)类别D为纯虚函数,因为其包含纯虚函数void display()。除此之外,D中还包括了虚函数virtual void showInfo(){…}。派生类E为类别D的派生类,且其实体类,其具体实现了纯虚函数display()的功能,并在E中对虚函数showInfo()进行了重定义。请在标有行号K*的地方给出纯虚函数display()的声明及虚函数showInfo()的重定义代码。

(3)在面向对象程序设计中,派生类的构造需要对直接基类和虚拟基类进行构造,请阅读代码并根据图示的继承结构,在标有行号W*的地方给出相应基类的初始化参数列表;

ABACB2B1DE #include using namespace std; class A { private: int x; public: A(int i):x(i) { cout<<\ } }; class B { private: int y; public: B(int j):y(j) { cout<<\ } }; class C { private: int z; public: C(int k):z(k) { cout<<\ } }; class B1:virtual public B, virtual public A //L1 { public: B1(int i, int j):B(i), A(j) //W1 { cout<<\ } }; class B2:public A, virtual public B //L2 { public: B2(int i, int j): A(i), B(j) { cout<<\ } }; class D { public: virtual void showInfo(){ cout<<”D::showInfo()”<

} public: void showInfo() //K2 { cout<<\派生类E中重定义的虚函数showInfo()\ } void display() { cout<<\派生类E中纯虚函数display()的具体实现\ } }; void main() { E e(1,2,3); } 2、 假设最终派生类E的继承体系结构如图所示。其中,类别B1, B2, D的多重

继承关系的声明按图从左到右的顺序进行,而带阴影的类别A,C,B表示其在继承体系中为虚基类。请根据以下要求进行程序填空: (1)在标有行号L*的地方给出类别B1, B2和E的声明;

(2)类别D为纯虚函数,因为其包含纯虚函数void display()。除此之外,D中还包括了虚函数virtual void showInfo(){…}。派生类E为类别D的派生类,且其实体类,其具体实现了纯虚函数display()的功能,并在E中对虚函数showInfo()进行了重定义。请在标有行号K*的地方给出纯虚函数display()的声明及虚函数showInfo()的重定义代码。

(3)在面向对象程序设计中,派生类的构造需要对直接基类和虚拟基类进行构造,请阅读代码并根据图示的继承结构,在标有行号W*的地方给出相应基类的初始化参数列表;

ABAB2B1CDE #include using namespace std; class A { private: int x; public: A(int i):x(i) { cout<<\ } }; class B { private: int y; public: B(int j):y(j) { cout<<\ } }; class C { private: int z; public: C(int k):z(k) { cout<<\ } }; class B1:virtual public B, virtual public A { public: B1(int i, int j):B(i), A(j) { cout<<\ } }; class B2:public A, virtual public B { public: B2(int i, int j): A(i), B(j) { cout<<\ //L1 //W1 //L2 } }; class D { public: virtual void showInfo(){ cout<<”D::showInfo()”<

4.1. 第1章 C++与面向对象程序设计概述(P21)

1、 若控制台中输入数据“12??345???634????3214?”,请写出标有行号L*的

程序的输出结果。(P21,第6(1)题,ex1-6-1.cpp) #include

void main(){ int a; char b; char c[4]; double d;

cin>>a>>b>>c>>d; //输入数据 cout<<\ //L1 cout<<\ //L2 cout<<\ //L3 cout<<\ //L4 }

答案:

L1: a=12 L2: b=3 L3: c=45 L4: d=634

2、 写出标有行号L*的程序的输出结果,要求严格符合控制格式。(P21,第

(2)题,ex1-6-2.cpp) #include #include void main(){

int a=20,b=18,c=24;

cout<<\ cout<

cout< cout<0 4 4.2. 第2章 C++基础(P57~58)

1、 请根据重载函数print(…)的定义,写出标有行号L*的程序的输出结果。(P57,

第10(1)题,ex2-10-1.cpp) #include

int print(int i){ return i*i; }

double print(double i){ return 2*i; } void main(){

int a=25; float b=9.2f; double d=3.3; char c='a'; short i=3; long k=9;

cout<

L1: 625

L2: 18.4 L3: 6.6

//L1

//L2 //L3 //L4 //L5 //L6

L4: 9409 L5: 9 L6: 81

2、 请根据变量的作用域和生存周期,写出标有行号L*的程序的输出结果,其

中,L4和L5行各有一个输出分支。(P57,第10(2)题,ex2-10-2.cpp) #include int n; int *p1; void fun(){ static int a; int b;

cout<<\ cout<<\}

void main(){ int *p2; int m; fun(); { int n(10),m(20); cout<<\ }

cout<<\ if(p1) cout<<\ if(p2) cout<<\} 答:

L1: a=0, b=-858993460

L2: n=10 L3: m=20 L4: n=0

L5: m=-858993460 L6: p2=0xCCCCCCCC

3、 阅读程序,请根据带默认参数的函数定义与调用原则,写出标有行号L*的

程序的输出结果。(P58,第10(3)题,ex2-10-3.cpp) #include double f(int a=10,int b=20,int c=5){ return a*b*c; } void main(){ cout<

L2: 2000 L3: 500 L4: 1000

4、 根据引用和返回引用的原理,阅读程序,请写出标有行号L*的程序的输出

结果。(P58,第10(4)题,ex2-10-4.cpp) #include using std::endl; using std::cout; int &f(int& a,int b=20){ a=a*b; return a; } void main(){ int j=10; int &m=f(j); int *p=&m; cout<

L2: 20 L3: 100 L4: 300

4.3. 第3章 类与对象(P99~100)

1、 请阅读程序,根据对象的构造原则和构造顺序,写出程序的输出结果。(P99,

第9(1)题,ex3-9-1.cpp) #include #include class X{

int a; char *b; float c; public:

X(int x1, char *x2, float x3):a(x1),c(x3){ //构造函数1 b=new char[sizeof(x2)+1]; strcpy(b,x2); }

X():a(0),b(\ //构造函数2 }

X(int x1,char *x2=\构造函数3 }

X(const X& other){ //构造函数4 a=other.a; b=\ c=other.c; }

void print(){ cout<<\ } };

void main(){

X *A=new X(4, \ X B, C(10), D(B); A->print(); //L1 B.print(); //L2 C.print(); //L3 D.print(); //L4 } 答:

L1: a=4, b=X::X(int,char,float), c=32

L2: a=0, b=X::X(), c=10 L3: a=10, b=X::X(....), c=10

L4: a=0, b=X::X(const X &other), c=10

2、 请阅读程序,根据对象指针的使用原则,写出程序的运行结果。(P100,第9

(2)题,ex3-9-2.cpp) #include using std::cout; using std::endl;

class Implementation { //类Implementation public:

Implementation(int v) { value = v; } void setValue(int v) { value = v; } int getValue() const { return value; } private:

int value; };

class Interface { //类Interface public:

Interface( int ); //声明 void setValue( int ); int getValue() const; private:

Implementation *ptr;//对象指针 };

Interface::Interface(int v):ptr(new Implementation(v)){ }

void Interface::setValue(int v) { ptr->setValue(v); }

int Interface::getValue() const {//常量函数:不修改数据成员的值 return ptr->getValue(); }

void main(){

Interface i(5);

cout<

cout<

L1: 5

L2: 10

3、 阅读程序,根据对象成员的构造原则和构造顺序,请按顺序写出程序的运行

结果。(P100,第9(3)题,ex3-9-3.cpp) #include using namespace std; class A{

int x; public:

A():x(0){ cout<<\ A(int i):x(i){ cout<<\ ~A(){ cout<<\};

class B{ int y; A X1; A X2[3]; public:

B(int j):X1(j),y(j){ cout<<\ ~B(){ cout<<\};

void main(){

A X1(1), X2(2); B B1(3); } 答:

从上到下X1 constructor... 依次为: X2 constructor...

X3 constructor... constructor A() called... constructor A() called... constructor A() called... B3 constructor... B3 destructor... X0 destructor... X0 destructor... X0 destructor... X3 destructor... X2 destructor... X1 destructor...

4.4. 第4章 继承(P131~132)

1、 请阅读程序,根据对象成员的含对象成员的派生类对象的构造顺序和构造原

则,按顺序写出程序的运行结果。(P131,第9(1)题,ex4-9-1.cpp) #include using namespace std; class A{ public:

A(int a,int b):x(a),y(b){ cout<<\ void Add(int a,int b){ x+=a;y+=b;}

void display(){ cout<<\ ~A(){ cout<<\private: int x,y; };

class B:private A{ private: int i,j; A Aobj; public:

B(int a,int b,int c,int d):A(a,b),i(c),j(d), constructor...\

void Add(int x1,int y1, int x2,int y2){ A::Add(x1,y1); i+=x2; j+=y2; }

void display(){ A::display(); Aobj.display(); cout<<\ }

~B(){cout<<\ };

void main(){ B b(1,2,3,4); b.display(); b.Add(1,3,5,7); b.display(); } 答:

从上到下A constructor... 依次为: A constructor...

B constructor... (1,2)(1,1)(3,4) (2,5)(1,1)(8,11) destructor B... destructor A... destructor A...

Aobj(1,1){ cout<<\

2、 请阅读程序,根据对象成员的含对象成员的派生类对象的构造顺序和构造原

则,按顺序写出程序的运行结果。(P131,第9(2)题,,ex4-9-2.cpp) #include using namespace std; class A{ public:

A(int a):x(a){ cout<<\ int f(){ return ++x; }

~A(){cout<<\private: int x; };

class B:public virtual A{ private: int y; A Aobj; public:

B(int a,int b,int c):A(a),y(c),Aobj(c){ cout<<\ int f(){ A::f(); Aobj.f(); return ++y; }

void display(){ cout<

~B(){cout<<\ };

class C:public B{ public:

C(int a,int b,int c):B(a,b,c),A(0){ cout<<\};

class D:public C,public virtual A{ public:

D(int a,int b,int c):C(a,b,c),A(c){ cout<<\ ~D(){cout<<\};

void main(){ D d(7,8,9); d.f();

d.display(); } 答:

从上到下A constructor...9 依次为: A constructor...9

B constructor...9 C constructor... D constructor...

12 12 11 destructor D....

destructor B... destructor A... destructor A...

4.5. 第5章 多态性(P156~157)

1、 请阅读程序,根据虚函数的特性,按顺序写出程序的运行结果。(P156,第4

(1)题,ex5-4-1.cpp) #include using namespace std; class Base{ protected: int n; public:

Base(int m){ n=m++; }

virtual void g1(){ cout<<\ g4(); } virtual void g2(){ cout<<\ virtual void g3(){ cout<<\g4(); } virtual void g4(){ cout<<\} };

class Derived:public Base{ //公有继承 int j; public:

Derived(int n1,int n2):Base(n1){ j=n2; }

void g1(){ cout<<\g2(); } void g3(){ cout<<\g4(); } };

void main(){

Derived Dobj(1,0); Base Bobj=Dobj; Bobj.g1();

cout<<\ Base *bp=&Dobj; bp->g1();

cout<<\ Base &bobj2=Dobj; bobj2.g1();

cout<<\ Dobj.g1(); } 答:

从上到下Base::g1()...1 依次为: Base::g4()...2

------------------

Deri::g1()...2 Base::g2()...3 Deri::g2()...4 Base::g4()...5 ------------------ Deri::g1()...6 Base::g2()...7 Deri::g2()...8 Base::g4()...9 ------------------ Deri::g1()...10 Base::g2()...11 Deri::g2()...12 Base::g4()...13

2、 请阅读程序,根据虚函数和纯虚函数的定义与特性,按顺序写出程序的运行

结果。(P156,第4(2)题,ex5-4-2.cpp) #include class Shape{ public:

virtual double area(){ return 0; } virtual void print()=0; };

class Circle:public Shape{ protected: double r; public:

Circle(double x):r(x){ }

double area(){ return 3.14*r*r; } //(1) void print(){ cout<<\//(2) };

class Cylinder:public Circle{ double h; public:

Cylinder(double r,double x):Circle(r),h(x){ }

double area(){ return 2*3.14*r*r+2*3.14*h; } //(3) };

void shapeArea(Shape &s){ cout<print(); } //(5) void main(){ Shape *s[3];

s[0]=&Circle(10);

s[1]=&Cylinder(20,100); for(int i=0; i<2; i++){

shapeArea(*s[i]); shapePrint(s[i]); } } 答: 说明:

i=0时,(4)-(1)-(5)-(2)-(1); i=1时,(4)-(3)-(5)-(2)-(3); 从上到下314

依次为: Circle : r=10 area=314

3140

Circle : r=20 area=3140

3、 请阅读程序,根据类型信息和类型转换的原理,按顺序写出程序的运行结果。

(P157,第4(3)题,ex5-4-3.cpp)——不要求! #include using namespace std; class A{ public:

void virtual f(){cout<<\};

class B:public A{ public:

void f(){cout<<\ void fb(){cout<<\};

class C:public A{ public:

void f(){cout<<\

void fc(){cout<<\};

void f(A *p){ p->f();

if (typeid(*p)==typeid(B)) { B *bp=dynamic_cast(p); bp->fb(); }

if (typeid(*p)==typeid(C)){ C *bc=dynamic_cast(p); bc->fc(); } }

void main(){

A *pa; B b; C c;

pa=&b; f(pa); pa=&c; f(pa); } 答:

从上到下f() in class B

依次为: normal function fb

f() in class C

normal function fc

4.6. 第6章 运算符重载(P183~185)

1、 请阅读程序,根据友元函数运算符重载的定义,按顺序写出程序的运行结果。

(P183,第5(1)题,ex6-5-1.cpp) #include class ABC{ int a,b,c; public:

ABC(int x,int y,int z):a(x),b(y),c(z){ }

friend ostream &operator<<(ostream &out,ABC& f); };

ostream &operator<<(ostream &out,ABC& f){

out<<\ return out; }

void main(){

ABC obj(10,20,30); cout<

从上到下a=10 依次为: b=20

c=30

2、 请阅读程序,根据对象赋值及构造的特性,按顺序写出程序的运行结果。

(P184,第5(2)题,ex6-5-2.cpp)——不要求! #include #include class X{ private: char *s; public:

X(char *b){ s=new char[sizeof(b)+1]; strcpy(s,b);

}

~X(){delete s;}

void display(){ cout<<\};

void main(){ X x1(\ X x2(x1); //拷贝构造(指针悬挂) X x3=x1; //拷贝构造(指针悬挂) x2.display(); x3.display(); } 答:

从上到下s=ok 依次为: s=ok

3、 请阅读程序,按顺序写出程序的运行结果。(P183,第5(1)题,ex6-5-3.cpp) #include class Number{ int n; public:

Number(int x):n(x){ }

Number& operator++(){ ++n; return *this; } Number& operator++(int){ n++; return *this;} friend Number &operator--(Number &o); friend Number &operator--(Number o, int);

void display(){ cout<<\ \};

Number &operator--(Number &o){ --o.n; return o; } Number &operator--(Number o,int){ o.n--; return o; } void main(){

Number N1(10); ++ ++ ++N1; N1.display(); N1++;

N1.display(); --N1;

N1.display(); N1-- -- --; N1.display(); } /*

This Number is: 13 This Number is: 14 This Number is: 13

This Number is: 13 */ 答:

从上到下This Number is: 13 依次为: This Number is: 14

This Number is: 13 This Number is: 13

4、 请阅读程序,按顺序写出程序的运行结果。(P183,第5(1)题,ex6-5-4.cpp)

——不要求! #include using namespace std; class Student{ private:

char *name; int age;

double Money; public:

Student(char *n=\Age=17,double Mey=1000.998):age(Age),Money(Mey){ name=new char[sizeof(n)+1]; strcpy(name, n); }

operator char*(){ return name; } //重载:函数调用运算符“()” operator int(){ return age; } //重载:函数调用运算符“()” operator double(){ return Money; } //重载:函数调用运算符“()” };

void main(){

Student s1(\阿瓦尔古丽\ char *Name=s1; //相当于:s1.char*() int Age=s1; //相当于:s1.int() double Money=s1; //相当于:s1.double()

cout<

cout<

从上到下阿瓦尔古丽 19 280001 依次为: 武昌鱼 17 1001

4.7. 补充题

1、 请阅读程序,根据对象的构造原则和构造顺序,按程序的执行顺序写出程序

的输出结果。注意:请在输出结果之前加“(*)”标示输出顺序。 #include using namespace std;

class A{ private: int x; public:

A():x(6){ cout<<\ }

A(int i):x(i){ cout<<\ }

~A(){ cout<<\ } };

class B{ int y; A x1[3]; A x2; public:

B(int j):y(j),x2(j){ cout<<\ }

~B(){ cout<<\ } };

void main(){

A a1(32), a2(50); B b1(23); } 答:

(1)A::A(int)--32 (2)A::A(int)--50 8)B::~B() 9)A::~A()

(((3)A::A()--6 (4)A::A()--6 (5)A::A()--6 (6)A::A(int)--23 (7)B::B(int)--23

(10)A::~A() (11)A::~A() (12)A::~A() (13)A::~A() (14)A::~A()

5. 程序设计题

5.1. 类与对象

5.1.1. 人员类Person

设计一个用于人事管理的人员类Person。具体要求如下:

(1)人员类Person具有四个数据成员:姓名name(字符指针char*类型)、身

份证号码sid(字符数组char[20]类型)、性别sex(char类型,男性’M’&女性’F’)、出生日期birthday。注意,不必考虑身份证中的可能有的日期与出生日期的一致性。其中,

a)出生日期birthday为一个对象成员,即日期类Date的内嵌对象。 b)日期类Date包括三个数据成员:年份year(int类型)、月份month(int

类型)、日子day(int类型);

c)日期类Date中具有一个含年、月、日三个参数的构造函数,月份和日期

两个参数具有默认参数值3月5日;

d)定义成员方法int getYear()、int getMonth()和int getDay(),分别用于返回

年月日信息;

(2)人员类Person具有两个重载的构造函数,其一只提供姓名、身份证号码、

性别和出生年份等四个参数,且性别参数具有默认值’M’、出生年份参数具有默认值1992;其二提供了姓名、身份证号码、性别、出生年/月/日等六个参数,且性别参数具有默认值’M’、 年月日参数具有默认值1986年4月7日。注意,在对象的构造函数定义中,必须使用初始化参数列表来实现对象成员的构造;

(3)为人员类Person提供自定义的析构函数,以回收动态分配给人员姓名的存

储空间;

(4)为人员类Person提供自定义的拷贝构造函数,实现人员对象的拷贝; (5)为人员类Person添加成员函数void display(),用于输出人员的具体信息;

具有上述功能的人员类Person的测试代码及相应输出结果如下: void main(){

Person wang(\ wang.display(); //L1

Person zhao(\王依\ zhao.display(); //L2

}

?

Person li = wang; li.display();

程序输出:

//或者 Person li(wang);

//L3

L1:姓名: Jasone, 身份证号: 350423X, 性别: M, 出生日期:1992年3月5日

L2:姓名: 王依, 身份证号: 362329X, 性别: F, 出生日期:1987年4月5日 L3:姓名: Jasone, 身份证号: 350423X, 性别: M, 出生日期:1992年3月5日

参考答案:

#include using namespace std;

class Date{ private: };

int getDay(){ }

return day; int getMonth(){ }

return month; int getYear(){ }

return year;

Date(Date &ad){//显式定义Date类的拷贝构造函数 }

this->year = ad.year; this->day = ad.day;

//等价于 year = ad.year

//等价于 month = ad.month //等价于 day = ad.day

this->month = ad.month; int year; int month; int day;

Date(int y, int m=3, int d=5){ //带默认参数的构造函数 }

this->year = y; this->month = m; this->day = d;

//等价于 year = y; //等价于 month = m; //等价于 day = d;

public:

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

Top