c语言程序设计教程第二版习题解答填空选择部分沈显军杨进才张勇讲解Word下载.docx
《c语言程序设计教程第二版习题解答填空选择部分沈显军杨进才张勇讲解Word下载.docx》由会员分享,可在线阅读,更多相关《c语言程序设计教程第二版习题解答填空选择部分沈显军杨进才张勇讲解Word下载.docx(22页珍藏版)》请在冰点文库上搜索。
2.
(1)叙述机器语言、汇编语言、高级语言的特点。
机器语言是计算机直接执行的语言,由二进制的0和1构成的一系列指令组成;
汇编语言是机器语言的助记符;
高级语言是接近人的自然语言习惯的编程语言,通过编译变成机器语言。
(2)结构化的语言与面向对象的语言是截然分开的吗?
不是截然分开的,面向对象的程序设计中也包含过程,含有结构化的思想。
(3)C编写的程序不加修改就可以在C++编译器中编译。
(5)C++程序通过编译变成带扩展名.obj的目标文件;
再通过连接变成带扩展名.exe的可执行文件。
(6)如果要求不使用include包含头文件,有什么办法使程序正常编译运行?
在相应的文件夹(子目录)中,找到需要包含的头文件,将头文件复制到包含处。
3.
(2)C++语言程序能够在不同操作系统下编译、运行,说明C++具有良好的移植性。
(可以说C++语言完全兼容C语言,但是在这不能说C++语言程序能兼容不同的操作系统;
对于计算机硬件,一般使用“兼容”一词,对于程序使用“移植”)。
(3)#include语句在程序运行前就执行了。
(4)C++程序运行时总是起始于main();
(5)用C++写程序时一个语句可分几行写。
(6)面向对象编程方法有:
对象、继承、类等。
1.2 习题2解答
(1)C++的基本数据类型可分为5大类:
逻辑型(或布尔型)、字符型、整形、实型、空值型。
分别用关键字bool,char,int,float/double,void 定义。
长度分别为1,1,4,4/8,不定字节。
整型、字符型的默认符号修饰为signed。
(2)十进制数值、八进制数值、十六进制数值的前缀分别为1~9,0,0x(或0X)。
(3)一个整数值的数据类型为int,一个带小数点的数据类型为double。
(4)C++预定义的常用转义序中,在输出流中用于换行、空格的转义序列分别为\n,\t。
(5)布尔型数值只有两个;
true, false。
在C++的算术运算式中,分别当作1,0。
(6)字符由单引号’’括起来,字符串由双引号“”括起来。
字符只能有1个字符字符串可以有多个字符。
空串的表示方法为“\0”(或“ ”)。
(7)标识符以英文字母,下划线开头。
(8)定义变量的同时赋初值的方法有赋值运算符=,括号。
定义常变量初值的方法有赋值运算符=,括号。
(9)关系运算符操作数的类型可以是任何基本数据类型,对其中的实数类型不能进行直接比较(if(a<
b)那么a和b为什么可以是float或double?
)
(-10)&
&
与||表达式按从左到右的顺序进行计算,以&
连接的表达式,如果左边的计算结果为false(或0),右边的计算不需要进行,就能得到整个逻辑表达式的结果:
false;
以||连接的表达式,如果左边的计算结果为true(或非0),就能得到整个逻辑表达式的结果:
true。
(11)>
运算符将一个数右移n位,相当于将该数除以2n,<
运算符将一个数左移n位,相当于将该数乘以2n。
(12)所有含赋值运算的运算符左边要求是左值。
(13)前置++、――的优先级高于后置++、――。
(14)按操作数数目分,运算符的优先级从高到低排列为单目、双目、三目,按运算符的性分,优先级从高到低排列为算术、移位、关系、按位、逻辑。
(15)在表达式中会产生副作用的运算符有++、--、各类赋值。
1.3习题3解答
(1)if语句中的表达式可以是任意表达式(关系表达式、逻辑表达式、算术表达式、常量)。
1.4习题4解答
(1)一个C++程序就是由一个个函数组成的即使是最简单的程序也有一个main( )函数。
(2)函数执行过程中通过return语句将函数值返回,当一个函数不需要返回值,此时需要使用void作为类型名。
(3)在C++中,如果函数定义在后,调用在先,需要进行函数原型声明,告诉编译器函数的(返回)类型,函数名,形式参数。
其格式和定义函数时的函数头的形式基本相同,它必须以分号 ;
结尾。
(4)函数调过程的3个步骤为:
函数调用(或参数传递),函数体执行,返回。
(5)函数参数传递过程的实质是将实参值通过堆栈一一传送给实参。
(实参传给实叁?
(6)递归程序分两个阶段执行调用,回代。
(7)带inline关键字定义的函数为内联函数,在编译时将函数体展开到所有调用处。
内联函数的好处是节省执行时间开销。
(8)函数名相同,但对应形参表不同的一组函数称为重载函数,参数表不同是指参数个数、类型不同。
(9)确定对重载函数中函数进行绑定的优先次序为精确匹配,对实参的类型向高类型转换后的匹配,实参类型向低类型及相容类型转换后的匹配。
(10)当既存在重载函数、又有函数模板,函数调用优先绑定重载函数,只有不能精确匹配重载函数时,才实例化类模板。
(11)内联函数的展开、重载函数的绑定、类模板的实例化与绑定均在编译阶段进行。
(12)在C++中,函数不允许嵌套定义,允许嵌套调用。
(1)voidfun(void)的定义是正确的,doublefun(intx;
inty)和intfun();
和doublefun(intx,y)这都是不正确的(定义是不能以;
结尾的)。
(2)函数intfun(intx,inty)的声明形式可以是intfun(int,int)和intfun(inty,intx);
和intfun(inti,intj);
(intfun(intx,inty)是不正确的因为函数的声明必须以;
结尾)。
(3)C++语言中规定函数的返回值的类型是由定义该函数时所指定的数据类型所决定。
(5)在C++中默认的形参值应该先从右边的形参开始向左边依次设置。
(6)重载函数参数个数相同时,参数类型必须不同。
(7)系统在调用重载函数时,依据的是函数名称、实参个数、实参类型。
(8)
(9)为了取代C中带参数的宏,在C++中使用内联函数。
(10)函数模板定义的头部template<
classt1,typenamet2,ints=0>
(11)若fun(8,3.1)调用的可以是fun(double,double)――(当没有精确匹配时,优先进行向高类型转换后的匹配)
(12)若fun(8,3.1)调用的可以是template<
classT1,classT2>
fun(T1,T2)
1.5 习题5解答
(-1)enumweekday{sun,mon,tue,wed=4,thu,fri,sat};
weekdayworkday=mon;
cout<
workday+wed<
endl;
输出:
5(怎么加的?
(2)在C++中,引用数组元素时,其数组下标的数据类型允许是整形常量、整形表达式等非浮点型表达式。
(整型表达式实际上包含了整型常量)
(3)设有数组定义:
chararray[]=”China”;
则数组array所占的空间为6个字节(’\0’)。
(4)若:
inta[][3]={1,2,3,4,5,6,7};
则a数组高维的大小为:
3。
(-6)若二维数组a有m列,则在a[i][j]前的元素个数为(i*m+j);
1.6习题六解答
1
(1)从变量的定义位置分,可分为全局变量与局部变量。
其中,局部变量定义在函数或复合语句中,供函数或复合语句中使用。
(2)变量的存储类型分为auto,extern,register,static。
当声明一个静态(static)变量,它既具有局部变量的性质,又具有全局变量的性质。
(3)C++程序的内存分为4个区:
全局数据区,代码区,栈区,堆区。
全局变量,静态变量,字符串常量存放在全局数据区,所有在函数和代码存放在代码区,为运行函数而分配的函数参数,局部变量,返回地址存放在栈区。
动态分配的内存在堆区。
(4)全局变量,静态变量具有静态生存期;
局部变量生存期为动态。
(5)函数原型中形参标识符的作用域为为函数原型,函数的形参与函数体作用域为块作用域;
函数,全局变量与常量有文件作用域。
(6)C++源程序中以#开头,以换行符结尾的行称为预处理命令。
预处理命令编译前由预处理器执行。
(7)可以通过3种方法使用名字空间,个别使用声明方式,全局声明方式,全局声明个别成员。
(1)在C++中,函数默认的存储类别为:
auto。
(2)函数的形式参数是局部变量,在一个函数体内定义的变量只在本函数范围内有效,在函数的复合语句中定义的变量在此复合语句中有效。
(3)#definePI3.14预处理命令必须以#开头,凡是以#开头的都是预处理命令行,在程序执行前执行预处理命令。
(4)动态分配的内存要用delete释放,局部auto变量分配的内存在函数调用结束时释放,全局变量的内存在程序结束时释放。
1.7 习题7解答
(1)类的私有成员只能被该类的成员函数或友元函数访问。
(2)类的数据成员不能在定义的时候初始化,而应该通过构造函数初始化。
(3)类成员默认的访问方式是private.
(4)类的公有成员函数的集合是该类给外界提供的接口。
(5)类的公有成员可以被类作用域内的任何对象访问。
(6)为了能够访问到某个类的私有成员,必须在该类中声明该类的友元。
(7)类的静态成员为该类的所有对象所共享。
(8)每个对象都有一个指向自身的指针,称为this指针,通过使用它来确定其自身的地址。
(9)运算符new自动建立一个大小合适的对象并返回一个具有正确类型的指针。
(-10)C++禁止非const成员函数访问const对象。
(-11)定义类的动态对象数组时,系统只能够自调用该类的构造函数对其进行初始化。
(――12)C++中语句constchar*constp=”hello”;
所定义的指针p和它所指的内容都不能被以改变。
(――13)假定AB为一个类,则语句AB(AB&
x);
为该类拷贝构造函数原型说明。
(14)在C++中访问一个对象的成员所用的运算符是 . ,访问一个指针所指向的对象的成员所用的运算符是->
。
(15)析构函数在对象的生存期结束时被自动调用,全局对象和静态对象的析构函数在程序运行结束时调用。
(16)设p是指向一个类的动态对象的指针变量,则执行deleteP;
语句时,将自动调用该类的析构函数。
(1)数据封装就是将一组数据和与这组数据有关操作组装在一起,形成一个实体,这实体也就是类。
(2)类的实例化就是创建类的对象。
(-3)已知p是一个指向类Sample数据成员m的指针,s是类Sample的一个对象。
如果要给m赋值为5:
s.*p=5;
(4)类与对象的关系和数据类型与变量的关系是相似的,一个对象只能属于一个具体的类。
(5)封装要求对象就具有明确的功能,它使得一个对象可以像一个部件一样用在各种程序中。
(6)内联函数是在编译时(而不是运行时)将该函数的目标代码插入到每一个调用该函数的地方。
(7)类中的函数成员可以在类体中定义,也可以在类体之外定义。
(8)C++中的对象并不是C语言中的结构体变量,它是一个状态和操作(或方法)的封装体,对象之间的信息传递是通过消息进行的。
(9)在建立类的对象时只为每个对象分配用于保存数据成员的内存
(1)类和数据类型有何关联?
类相当于一种包含函数的自定义数据类型,它不占内存空间,是一个抽象的“虚”体,使用已定义的类建立对象就像用数据类型定义变量一样。
对象建立后,对象占据内存,变成了一个“实”体。
类与对象的关系就像数据类型与变量的的关系一样。
其实,一个变量就是一个简单的不含成员函数的数据对象。
(2)类和对象的内存分配关系?
为节省内存,编译器在创建对象时,只为各对象分配用于保存各对象数据成员初始化的值,并不为各对象的成员函数分配单独的内存空间,而是共享类的成员函数定义,即类中成员函数的定义为该类的所有对象所共享,这是C++编译器创建对象的一种方法,实际应用中,我们仍将对象理解为由数据成员和函数成员两部分组成。
(3)什么是浅拷贝?
什么是深拷贝?
二者有何异同?
构造函数用于建立对象时给对象赋初值以初始化新建立的对象。
如果有一个现存的对象,在建立新对象时希望利用现存对象作为新对象的初值,即用一个已存在的对象去初始化一个新建立的对象。
C++提供的拷贝构造函数用于在建立新对象时将已存在的对象的数据成员值复制给新,以初始化新对象。
拷贝构造函数在用类的一个对象去初始化该类的另一个对象时调用,以下3种情况相当于用一个已存在的对象去初始化新建立的对象,因此,调用拷贝构造函数:
1当用类的一个对象去初始化该类的另一个对象时。
2如果函数的形参是类的对象,调用函数时,将对象作为函数实参传递给函数的形参时。
3如果函数的返回值是类的对象,函数执行完成,将返回值返回时。
原因在于默认的拷贝构造函数实现的只能是浅拷贝,即直接将原对象的数据成员值依次复制给新对象中对应的数据成员,并没有为新对象另外分配内存资源。
这样,如果对象的数据成员是指针,两个指针对象实际上指向的是同一块内存空间。
当类的数据成员中有指针类型时,我们就必须定义一个特定的拷贝构造函数,该拷贝构造函数不仅可以实现原对象和新对象之间的数据成员的复制,而且可以为新的对象分配单独的内存资源,这就是深拷贝构造函数。
(4)什么是this指针?
它的作用是什么?
一个类的成员函数中,有时希望引用调用它的对象,对此,C++采用隐含的this指针来实现。
this指针是一个系统预定义的特殊指针,指向当前对象,表示当前对象的地址。
系统利用this指针明确指出成员函数当前操作的数据成员所属的对象。
实际上,当一个对象调用其成员函数时,编译器先将该对象的地址赋给this指针,然后调用成员函数,这样成员函数对对象的数据成员进行操作时,就隐含使用了this指针。
一般而言,通常不直接使用this指针来引用对象的成员,但在某些少数情况下,可以使用this指针,如重载某些运算符以实现对象的连续赋值等。
This指针不是调用对象的名称,而是指向调用对象的指针的名称。
This的值不能改变,它总是指向当前调用对象。
(5)C++中静态成员有何作用?
它有何特点?
C++提供了静态成员,用以解决同一个类的不同对象之间数据成员和函数的共享问题。
静态成员的特点是:
不管这个类创建了多少个对象,其静态成员在内存中只保留一份副本,这个副本为该类的所有对象所共享。
面向对象方法中还有类属性(classattribute)的概念,类属性是描述类的所有对象的共同特征的一个数据项,对于任何对象实像实例,它的属性值是相同的,C++通过静态数据成员来实现类属性。
(6)友元关联有何性质?
①友元关联是不能传递的,不能被继承。
如B类是A类的友元,C类是B类的友元,C类和A类之间如果没有声明,就没有任何友元关系,不能进行数据共享。
②友元关系是单向的,不具有交换性,如果声明B类是A类的友元,B类的成员函数就可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有和保护数据。
(7)在C++程序设计中,友元关系的优点和缺点是什么?
友元概念的引入,提高了数据的共享性,加强了函数与函数之间、类与类之间的相互联系,大大提高了程序的效率,这是友元的优点,但友元也破坏了数据隐蔽和数据封装,导致程序的可维护性变差,给程序的重用和扩充埋下了深深的隐患,这是友元的缺点。
(8)如何实现不同对象的内存空间的分配和释放?
当类被实例化成对象后,不同类别的对象占据不同类型的内存,其规律与普通变量相同:
1类的全局对象占有数据段的内存。
2类的局部对象内存分配在栈中。
3函数调用时为实参建立的临时对象内存分配在栈中。
4使用动态内存分配语句new建立的动态对象,内存在堆中分配。
虽然类(对象)是由数据成员与成员函数组成。
但是,程序运行时,系统只为各对象的数据成员分配单独内存空间,而该类的所有对象则共享类的成员函数定义以及为成员函数分配的空间。
对象的内存空间分配有下列规则:
1对象的数据成员与成员函数占据不同的内存空间,数据成员的内存空间与对象的存储类别相关,成员函数的内存空间在代码段中。
2一个类所有对象的数据成员拥有各自的内存空间。
3一个类所有对象的成员函数为该类的所有对象共享,在内存中,只有一个副本随着对象的生命周期的结束,对象所占的空间就会释放,各类对象内存空间释放时间与方法如下:
a.全局对象的数据成员占有的内存空间在程序结束时释放。
b.局部对象与实参对象数据成员的内存空间在函数调用结束时释放。
c.动态对象数据成员的内存空间要使用delete语句释放。
d.对象的成员函数的内存空间在该类的所有对象生命周期结束时自动释放。
1.8 习题8解答1 .
(1)C++程序设计的关键之一是利用继承实现软件重用,有效地缩短程序的开发时间。
(2)基类的对象可以作为派生类的对象使用,这称为类型兼容(或赋值兼容)。
(3)在C++中, 三种派生方式的说明符号为public, private, protected, 如果不加说明,则默认的派生方式为private。
(4)当私有派生时,基类的的公有成员成为派生类的私有成员;
保护成员成为派生类的私有成员;
私有成员成为派生类的不可访问成员。
(5)相互关联的各个类之间的关系主要分为组成关联和继承关联。
(6)在派生类中不能直接访问基类的私有成员否则破坏了基类的封装性。
(-7)保护成员具有双重角色,对派生类的成员函数而言,它是公有成员,但对所在类之外定义的其它函数而言则是私有成员。
(-8)多继承时,多个基类中的同名的成员在派生类中由于标识符不唯一而出现二义性。
在派生类中采用成员名限定或重定义具有二义性的成员来消除该问题。
(9)C++提供的多继承机制允许一个派生类继承多个基类。
(1)一个派生类可以作为另外一个派生类的基类;
派生类至少有一个基类;
派生类的成员除了它自己的成员外,还包含了它的基类的成员。
(2)在多继承中,公有派生和私有派生对于基类成员在派生类中的可访问性与单继承的规则是完全相同的。
(3)友元关系是不能继承的。
(4)派生类一般都是公有派生;
对基类成员的访问必须是无二义性的;
赋值兼容规则也是适用于多重继承的场合。
(5)基类的保护成员在公有派生中仍然是保护的;
基类的保护成员在私有派生中却是私有的;
对基类成员的访问必须是无二义性的。
(6)在公有派生的情况下,派生类中定义的成员函数只能访问原基类中的公有成员和保护成员。
(7)每个派生类的构造函数都要为虚基类构造函数提供实参;
多继承时有可能出现对基类成员访问的二义性问题;
建立派生类对象时,虚基类数的构造函数会首先被调用。
(8)在一个派生类对象结束其生命周期时先调用基类的析构函数后调用派生类的析构函数。
(9)当保护继承时,基类的公有成员和保护成员在派生类中成为保护成员,不能通过派生类的对象来直接访问。
(10)若派生类的成员函数不能直接访问基类中继承来的某个成员,则该成员一定是基类中的私有成员。
(11)设置虚基类的目的是消除二义性。
(12)继承具有传递性,即当基类本身也是某个类的派生类时,底层的派生类也会自动继承间接基类的成员。
(13)在派生类构造函数的初始化列表中不能包含派生类中一般数据成员的初始化。
(14)在公有派生情况下,派生类的对象可以赋给基类的对象;
派生类的对象可以初始化基类的引用;
派生类的对象的地址可以赋给指向基类的指针。
(1)派生类如何实现对基类私有成员的访问?
无论使用哪一种继承方式,基类的私有成员都不允许外部函数直接访问,也不允许派生的成员函数直接访问,但是可以通过基类的公有成员函数间接访问该类的私有成员。
(2)什么是赋值兼容?
它会带来什么问题?
类型兼容是指在公有派生的情况下,一个派生类对象可以作为基类的对象来使用。
类型兼容又称为类型赋值值兼容或类型适应。
在C++中,类型兼容主要指以下3种情况:
1派生类对象可以赋值给基类对象;
2派生类对象可以初始化基类的引用;
3派生类对象的地址可以赋给指向基类的指针;
由于派生类对象中包含基类子对象,所以这种引用方式是安全的,但是这种方法只能引用从基类继承的成员。
如果试图通过基类指针引用那些只有在派生类中才有的成员,编译器将会报告语法错误。
(3)多重继承时,构造函数和析构函数的执行顺序是如何实现的?
多得继承时,构造函数的执行顺序是:
先执行基类的构造函数,再执行对象成员的构造函数,最后执行派生类的构造函数。
在多个基类之间则严格按照派生类声明时从左到右的顺序来执行各基类的构造函数,而析构函数的执行顺序则正好与构造函数的执行顺序相反。
(4)继承与组合之间的区别和联系是什么?
继承描述的是一般类与特殊类的关系,类与类之间体现的是”isakindof”,即如果在逻辑上A是B的一种,允许A继承B的功能和属性。
例如汽车(automobile)是交通工具(vehicle)的一种,小汽车(car)是汽车的一种。
那么类automobile可以从类vehicle派生,类car可以从类automobile派生。
组合描述的是整体与部分的关系,类与类之间体现的是”isapartof”,如果在逻辑上A是B的一部分,则允许A和其他数据成员组合为B。
例如:
发动机、车轮、电池、车门