华科研究生C++复习50题和答案.docx
《华科研究生C++复习50题和答案.docx》由会员分享,可在线阅读,更多相关《华科研究生C++复习50题和答案.docx(32页珍藏版)》请在冰豆网上搜索。
华科研究生C++复习50题和答案
复习范围:
所有讲过的内容。
下面的复习题基本涵盖所有考试内容,请认真作答,并重在理解。
考试时间:
2014.4.2614:
30——17:
00
简答题
1.什么是程序?
什么是程序设计?
什么是程序设计语言?
程序是用程序设计语言表示的计算机的解题算法或解题任务。
程序设计是将解题任务转变为程序的过程。
程序设计语言是由一些符号所构成的集合,这些符号可用于定义、组织并完成各种各样的计算任务。
2.类型的强弱指的是什么?
什么是无类型语言、强类型语言、弱类型语言?
C++语言属于哪种?
强类型定义语言:
一种总是强制类型定义的语言,要求变量的使用要严格符合定义,所有变量都必须先定义后使用。
java、.NET、C++等都是强制类型定义的。
也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。
与其相对应的是弱类型语言:
数据类型可以被忽略的语言。
它与强类型定义语言相反,一个变量可以赋不同数据类型的值。
3.什么是抽象数据类型?
C++是通过什么方式实现抽象数据类型的?
由一组对象和一组在这些对象上的操作所组成,利用数据抽象机制把一个数据类型的表示和操作汇集起来,封装在一起,定义成一个新的数据类型,这种新的数据类型统称为抽象数据类型。
引入类类型。
4.C++中标识符的命名规则是什么?
什么是合法的标识符,什么是不合法的标识符
1、大小写英文字母,下划线(_),以及阿拉伯数字组成。
2、标识符的第一个字符必须是大小写英文字母或者下划线,而不能是数字。
合法命名非法命名
wiggles$Z]**/* $、]和*都是非法字符*/
cat22cat/*不能以数字开头*/
Hot_TubHot-Tub/*-是非法字符*/
taxRatetaxrate/*不能有空格*/
_kcabdon't/*'是非法字符*/
5.什么是引用机制?
指针和引用有什么区别和联系?
允许程序正文中通过引用为已有名字的内存单元声明新的名字,这个新名字成为该内存单位已有名字的引用名,俗称别名。
相同点:
都是地址的概念;
指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。
区别:
1、指针是一个实体,而引用仅是个别名;
2、引用使用时无需解引用(*),指针需要解引用;
3、引用只能在定义时被初始化一次,之后不可变;指针可变;
4、引用没有const,指针有const;
5、引用不能为空,指针可以为空;
6、“sizeof引用”得到的是所指向的变量(对象)的大小,而“sizeof指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
7、指针和引用的自增(++)运算意义不一样;
8、从内存分配上看:
程序为指针变量分配内存区域,而引用不需要分配内存区域。
联系:
在既能使用指针也能使用引用的情况下,使用引用要安全一些,因此应该尽量使用引用。
6.函数调用时的两种参数传递方式是什么?
深入理解值调用和引用调用。
一种是按值传递,一种是按地址传递。
按值传递就是在子函数中开辟出一个临时内存空间,将传递的数值保存在这个空间中,当子函数结束后,这个内存空间就会释放了。
按地址传递则是把主函数开辟的某个内存空间首地址传递给子函数,子函数可以直接读写主函数上这段内存空间,当子函数结束后,这部分空间不会被释放,主函数将继续使用这段空间。
传值:
函数调用入口参数时,一般都会创建副本或者调用类对象的拷贝构造函数,所以操作结束后入参的值没有变化,变化的只是副本。
引用:
则是直接操作原来的对象,不会建立副本,对该对象做的操作,会直接影响到原来传入的变量或者对象。
C++传值调用需要创建一个实参副本,所以要重新开辟一块内存,进行赋值拷贝动作。
引用传参,因为引用是变量的别名,所以不需要进行重新分配内存,重新赋值,可以节约系统资源。
7.什么是内联函数?
内联函数的作用是什么?
用inline关键字定义的函数。
内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处。
编译时,类似宏替换,使用函数体替换调用处的函数名。
作用:
内联扩展是用来消除函数调用时的时间开销。
它通常用于频繁执行的函数。
8.使用class、struct和union关键字声明类的区别是什么?
class 对象封装,具有多态等特性。
struct的成员默认是public的,是class的特列,class能对有对数据的隐秘机制,struct没有。
union,不论其内部有多少成员,在任意时刻,只有一个可用,因为所有成员公用的一个地址,其大小为最大那个数据的大小。
9.什么是封装、继承、派生、多态?
封装:
隐藏内部的行为和信息,使用者只用看到对外提供的接口和公开的信息。
继承:
可以利用已有的数据类型来定义新的数据类型。
所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。
派生:
从已有的类(父类)产生一个新的子类,称为类的派生。
派生类是基类的具体化,而基类则是派生类的抽象。
多态:
一种消息被不同类型的对象接收时会导致不同行为的实现。
10.什么是对象?
类和对象有什么区别和联系?
类是具有相同数据结构(属性)和相同操作功能(行为)对象的集合。
对象就是符合某种类所产生的一个实例。
对象与类的关系是:
对象的共性抽象为类,类的实例化就是对象。
11.类成员有哪三种访问控制权限?
各自对类成员的访问带来什么影响?
访问控制属性有以下三种:
public,private和protected。
1、公有类型成员用public关键字声明,任何一个来自类外部的访问都必须通过这种类型的成员来访问(“对象.公有成员”)。
公有类型声明了类的外部接口。
2、私有类型成员用private声明(若私有类型成员紧接着类名称,可省略关键字),私有类型的成员只允许本类的成员函数来访问,而类外部的任何访问都是非法的。
这样完成了私有成员的隐蔽。
3、在不考虑继承的情况下,保护类型(protected)的性质和私有类型的性质一致。
即保护类型和私有类型的性质相似,其差别在于继承过程中对产生的新类影响不同。
就派生类而言,保护保护成员对于他们来讲好像就是共有成员。
12.什么是拷贝赋值操作?
为什么要对赋值操作的语义进行扩充?
为类对象中所有数据成员依次进行拷贝赋值。
因为左操作数为类类型的对象,简单赋值操作无法满足需求。
13.什么是成员函数的内联实现?
有哪两种形式?
将类中的成员函数定位为内联函数称为成员函数的内联实现。
1、在类声明中完全定义实现的成员函数成为内联成员函数。
2、用关键字inline定义的成员函数成为内联函数。
14.什么是成员函数的重载?
区分重载的标识有哪些?
在同一个类中用一个标示符为两个或两个以上的成员函数命名成为成员函数的重载。
参数的个数和参数的类型可以作为重载函数相互区分的标志。
15.什么是类的静态成员?
定义类的静态成员的作用是什么?
和普通类成员相比有什么区别?
在c++类中声明成员时可以加上static关键字,这样声明的成员就叫做静态成员(包括数据成员和成员函数)。
在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。
因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。
使用静态数据成员可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。
静态数据成员的值对每个对象都是一样,但它的值是可以更新的。
只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。
16.静态数据成员、常数据成员、基类子对象、对象成员的初始化方式是什么?
staticinta;
constintc;
classA{
private:
inta;
public:
A(){}
};
classBaseClass{
private:
Aa1;
publicBaseClass(){}
};
类名对象名n(初值n);
17.理解和区分以下概念:
常指针、指向常量的指针,举例说明。
1.常量指针(常指针)
int*constp
特点是指针指向的数值可以改变,然而指针所保存的地址却不可以改变。
2.指针常量
constint*p
特点是指针所保存的地址可以改变,然而指针所指向的值却不可以改变。
同理,当添加*p=b时,会发生编译错误。
3.指向常量的常指针
constintconst*p
特点是指针所保存的地址不可变,指针所指向的数值也不可变。
18、什么是构造函数、析构函数?
它们能否被重载?
构造函数:
通俗的讲,在类中,函数名和类名相同的函数称为构造函数。
它的作用是在建立一个对象时,作某些初始化的工作(例如对数据赋予初值)。
析构函数:
当一个类的对象离开作用域时,析构函数将被调用(系统自动调用)。
析构函数的名字和类名一样,不过要在前面加上~。
对一个类来说,只能允许一个析构函数,析构函数不能有参数,并且也没有返回值。
析构函数的作用是完成一个清理工作,如释放从堆中分配的内存。
构造函数可以被重载,析构函数不可以被重载。
因为构造函数可以有多个且可以带参数,而析构函数只能有一个,且不能带参数。
19.什么是缺省构造函数?
什么是有参构造函数?
缺省构造函数:
当声明对象的时候,编译器会调用一个构造函数。
若声明的类中没有声明构造函数,编译器会自动调用一个缺省构造函数,该函数相当于一个不接受任何参数,不进行任何操作的构造函数。
而当类中已经有声明的构造函数时,编译器就不会调用缺省构造函数。
有参构造函数:
带参数的构造函数。
Point类声明:
Point();//缺省
Point(intx,inty);//有参
20.什么是拷贝构造函数?
它会在哪些情况下被系统自动调用?
拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。
三种情况下系统自动调用copy构造函数:
1.定义语句中用同类的已有对象初始化另一个对象.例如:
A a(b);
2.将一个对象以按值传递的方式传给另一个对象时生成对象副本. 例如:
A fun(A a);
3.生成一个临时对象作为函数返回的结果.例如:
return a;
21.什么是友元函数、友元类?
友元函数在声明上与普通函数有什么区别?
友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。
类授予它的友元特别的访问权。
通常同一个开发者会出于技术和非技术的原因,控制类的友元和成员函数(否则当你想更新你的类时,还要征得其它部分的拥有者的同意)。
Friend函数名(函数声明)。
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。
定义友元类的语句格式如下:
friendclass类名(即友元类的类名);
其中:
friend和class是关键字,类名必须是程序中的一个已定义过的类。
22、有哪些访问控制?
在访问控制修饰符的修饰下,当前类中的名字在水平模块中的访问规则是什么?
访问权限:
public,protected,private
访问规则:
1、水平模块部分能访问当前类、当前类的直接派生类以及当前类的间接派生类中由public访问控制修饰符修饰的共有成员。
2、水平模块部分能访问当前类的直接派生类和当前类的间接派生类中由公有继承所得到的基类子对象中的公有成员。
3、对于当前类、当前类的直接派生类以及当前类的间接派生类中由公有继承所得到的基类子对象中保护成员和私有成员,在水平模块部分不能对它们访问。
23.什么是作用域?
有哪些类型?
作用域是指标示符的作用范围或有效范围。
对象的作用域包括:
1、函数原型的作用域,指函数原型中标示符形参的作用范围,其作用域始于函数原型声明的左括号“(”,结束于函数原型声明的右括号“)”;
2、块作用域,指在块声明的标示符,其作用域自声明处起,一直到块结束为止;
3、类作用域,指类声明中一对花括号所形成的作用范围,简称类域。
4、文件作用域,不在前述各个作用域中出现的声明,具有文件作用域,如文件开头所定义的全局标示符就具有全局作用域。
24.什么是可见性?
它的一般规则有哪些?
可见性是从对标示符引用的角度来谈的概念,即若标示符在某处可见,则就可以在该处引用该标示符,这里所说的标示符主要是指变量或者对象。
一般规则:
1、标示符应声明在先,引用在后。
2、在同一作用域中,不能声明同名的标示符。
3、如果某个标示符在外层中声明,且在内层中没有同一标示符的声明,则该标示符在内层可见。
4、对于两个嵌套的作用域,如果在内层作用域内声明了与外层作用域中同名的标示符,则外层作用域的标示符在内层不可见。
25.什么是常对象、常引用、常指针、指向常量的指针?
常对象:
指常量对象,其必须进行初始化,且不能被更新,类名const<对象名>或者const<类名><对象名>。
常引用:
使用const修饰符说明的引用,const<类型说明符>&<引用名>。
常指针:
指带常量的指针,因const位置不同,含义也不同。
Char*constptr1=stringptr1;ptr1指向常量。
constChar*ptr2=stringptr2;ptr2指向字符串。
26.什么是常数据成员、常成员函数?
如何使用它们?
常数据成员:
使用const说明的数据成员,其只能通过成员初始化列表的方式来生成构造函数以便对数据成员作初始化。
常成员函数:
使用const说明的成员函数,<类型说明符><函数名>(<参数表>)const;
27.什么是静态数据成员、静态成员函数?
它们有什么特点?
静态数据成员:
使用static关键字定义的数据成员被称为静态数据成员,静态数据成员所属类的所有实例都共享相同的静态成员值。
静态成员函数:
使用static关键字定义的成员函数被称为静态成员函数,其有如下特点:
1、静态成员函数也属于整个类。
无论定义多少类的对象,它只有一个拷贝;
2、静态成员函数也是用static来声明的;
3、在程序中可以使用类名或对象名来调用静态成员函数,而一般的成员函数则只能通过对象名来调用;
4、静态成员函数只能访问属于该类的静态数据成员或静态成员函数,而不能访问其他成员。
28.什么是类的友元?
类的友元有哪两种?
当一个类为另一个类的友元时,该类的所有成员都能访问对方类的私有、保护成员。
friendclass类名(即友元类的类名);
其中:
friend和class是关键字,类名必须是程序中的一个已定义过的类。
类的友元有哪两种?
:
友元函数和友元类。
29.掌握包含命令(#include)、宏定义命令(#define)、条件编译命令(#if)的基本用法。
包含命令(#include):
头文件通过include预处理器指示符(preprocessorincludedirective)而成为我们程序的一部分。
预处理器发现#include指令后,就会寻找后跟的文件名并把这个文件的内容包含到当前文件中。
被包含文件中的文本将替换源代码文件中的#include指令,就像你把被包含文件中的全部内容键入到源文件中的这个位置一样。
文件包含的两种格式<>、“”区别在于:
文件名用<>括起来,表示嵌入由C++系统提供的存放标准库路径中的头文件,这种方式是标准方式;将文件名用双引号“”括起来,表示首先查找用户自定义工作路径中的头文件,若找不到,再按标准方式进行查找。
宏定义命令(#define):
#define是C++语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率。
该命令有两种格式:
一种是简单的宏定义,另一种是带参数的宏定义。
(1) 简单的宏定义:
#define <宏名> <字符串>
例:
#define PI 3.1415926
(2) 带参数的宏定义 #define <宏名> (<参数表>) <宏体>
例:
#define A(x) x
条件编译命令(#if):
希望根据一定的条件编译源文件的部分语句,有5种使用形式,详见课本P170。
30.如何应用#define定义带有参数的宏?
如max(x,y);
#definemax(x,y)(宏体)
31、什么是对象的生存期?
有哪两种?
对象在什么情况下具有静态生存期?
根据生存期的不同可以把对象分为哪三种?
各具有什么特点?
对象从产生到结束的这段时间就是它的生存期,在对象生存期内,对象将保持它的值,直到其被更新为止。
动态生存期和静态生存期。
若对象的生存期与程序运行期相同,则称该对象具有静态生存期。
1、局部对象:
当对象被声明时调用构造函数,该对象被创建;当程序退出定义该对象所在的函数体或程序块时,调用析构函数,释放该对象。
2、静态对象:
当程序第一次执行所声明的静态对象时,该对象被创建;当程序结束时,该对象被释放。
3、全局对象:
当程序开始时,调用构造函数创建该对象;当程序结束时调用析构函数释放该对象。
32.什么是对象数组?
对象数组和普通数组有什么不同?
组成数组的各个元素的数据类型都是对象。
1、组成元素不同。
2、初始化不同,基本类型数组的初始化使用初值去初始化变量,对象数组的初始化则是用初值去构造对象的初始状态,需要调用类中的相应构造函数来完成。
3、存储结构不同。
33.简述操作符重载的必要性
将已经定义的、有一定功能的操作符进行重新定义,来完成更为细致具体的运算等功能,便于外部调用而无需知晓内部具体运算过程。
34.掌握+、-等算术运算符、赋值操作符=、下标操作符[]、类成员访问操作符->、增量++/减量--操作符等的重载
基本形式:
返回类型operator操作符(参数列表){}。
操作符重载函数是一个函数,只不过这个函数的函数名为operator再加上后面要重载的操作符而已,比如要重载+号,则:
hyongoperator+(hyongm){}这就声明了一个返回类型为hyong的操作符函数,其函数名为operator+
调用方式
1、调用类中的操作符重载函数的方法:
当调用类中定义的操作符重载函数时最左边的对象是调用操作符重载函数的对象。
比如在类hyong中重定义的+操作符hyongoperator+(hyongm){},有类hyong的对象m和n则调用操作符重载函数的方法有m+n和m.operator+(n),前一条语句会自动转换为后面这条语句,且m+n的表达式中最左边的对象是调用操作符重载函数的对象,而最右边的那个将被作为参数传送。
也就是说n+m会转换成n.operator+(m)。
要记住当调用类中定义的操作符重载函数时最左边的对象是调用操作符重载函数的对象。
2、调用友元或独立的操作符重载函数的方法:
当调用类的友元操作符重载函数或独立的操作符函数时语句m+n会转换为显示的调用方式,比如有友元或独立操作符重载函数hyongoperator+(hyonga,hyongb){}则当出现m+n时会转换成语句operator+(m,n)表达式的第一个对象传给第一个参数,第二个对象传给第二个参数。
35.区分指针数组、数组指针、指针函数、函数指针的概念,对一下声明能正确解释其含义:
(1)int(*p1)[3];
(2)Location*P2[5];(3)Point(*Fp)(int,int);(4)Location*Pf(LocationA);(5)Location(*Fp_ary[2])(char*,int*);
(1)int(*p1)[3]数组指针,表示:
指向数组p1的指针,元素表示:
(*p1)[i] ;
(2)Location*P2[5]指针函数
(3)Point(*Fp)(int,int)函数指针
(4)Location*Pf(LocationA)指向类成员的指针
(5)Location(*Fp_ary[2])(char*,int*)不会
36.为什么说void*类型的指针是准通用型指针?
一个指向任何对象类型的指针都可以赋值给类型为void*的变量,void*可以赋值给另一个void*,两个void*可以比较相等与否,而且可以显式地将void*转换到另一个类型。
其它操作都是不安全的,因为编译器并不知道实际被指的是哪种对象。
因此,对void*做其他任何操作都将引起编译错误。
要使用void*,就必须显式地将经转换到某个指向特定类型的指针,因此void*指针只支持几种有限的操作,即为准通用型指针。
37.什么是多重指针?
指针P由于占用存储单元而有自己的地址,因此也可以被另外的指针PP指向。
同时,指针PP同样可以被另一个指针PPP所指向。
这样就形成多种指针的概念。
声明一个T类型的N重指针的一般形式为:
T**…*p;
38.掌握动态存储管理中的new、delete、new[]、delete[]的用法。
new操作:
T是数据类型名,E是运算表达式,一般形式为:
newT(E)功能是动态创建一个T类型的对象并用初值表达式E中的初值对其进行初始化。
delete操作:
deletep;删除P对象。
new[]用于动态创建数组类型的对象,设T是数据类型名,E是算数常量表达式,一般形式为newT[E];
delete[]用于清除用new[]动态创建的数组类型的对象,一般形式为delete[]表达式或者delete[]p;
39.掌握用typedef对类型及类型定义表达式命名的方法。
解释typedefchar*(*p_to_fun)(char*,char*);的含义。
一般形式:
typedef已有数据类型名标示符表列;
例如typedefunsignedintUINT,size_t;将UINT,size_t都定义为unsignedint类型。
typedefchar*(*p_to_fun)(char*,char*);是类型定义表达式,p_to_fun是用于命名的标示符,char*(*)(char*,char*)则是类型表达式,通过typedef将p_to_fun定义成为类型表达式char*(*)(char*,char*)的名字。
40.String类的声明和实现。
要想使用标准C++中string类,必须要包含#include//注意是,不是,带.h的是C语言中的头文件
实现方法详解课本P290
41、什么是this指针?
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。
this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。
也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。
例如,调用date.SetMonth(9)<===>SetMonth(&date,9),this帮助完成了这一转换。
使用方法:
一种情况就是,在类的非静态成员函数中返回类对象本身的时候,直接使用return*this;另外