所用教材《C++程序设计教程(修订版)——设计思想与实现》,钱能著。
第1章 C++入门
- 程序开发过程:编辑——编译——连接——运行
编辑是将C++源程序输入计算机的过程,保存文件名为cpp。
编译是使用系统提供的编译器将源程序cpp生成机器语言的过程,目标文件为obj,由于没有得到系统分配的绝对地址,还不能直接运行。
连接是将目标文件obj转换为可执行程序的过程,结果为exe。
运行是执行exe,在屏幕上显示结果的过程 - 每个以符号“ # ”开头的行,称为编译预处理行。
- C++中,一个函数必须在函数声明后才能使用(被调用)。
C++函数声明总是由函数原型构成。
参数声明时,要指出其类型。 - 函数定义中的参数称为形式参数,简称形参。
调用函数时实际传递的值称为实际参数,简称实参。 - C/C++标准都对main()函数中不写return语句予以了默许。
- 函数定义包含函数声明,所以可以将函数定义放在函数应该声明的位置,而将其他函数的定义放在主函数main()之前。
- 函数定义不能嵌套。
第2章 基本数据类型与输入输出
- C++中,保留字也称关键字。它是预先定义好的标识符。
以下列举几个自己没有用过或很少用过的保留字防止题目出偏出怪:
typedef、volatile、union、catch、dynamic_cast、reinterpret_cast、explicit、mutable、throw、const_cast、static_cast、try、typeid、wchar_t、typename、asm、cdecl、far、huge、interrupt、near、pascal、export、except、fastcall、saveregs、stdcall、seg、syscall、fortran、thread - 在程序中用到的其他名字(标识符)不能与C/C++的关键字有相同的拼法和大小写。关键字也不能重新定义。
- 在16位计算机上,整型变量占2个字节。
在32位计算机上,整型变量占4个字节。 - 在大多数计算机上,short int 表示2个字节长。short 只能修饰int,short int 可以省略为short。
- long 只能修饰 int 和 double 。修饰为 long int(可以省略为long)时,一般表示4个字节,修饰 long double 时,一般表示10个字节。
- unsigned 和 signed 只能修饰 char 和 int。一般情况下,默认的 char 和 int 为signed。实型数 float 和 double 总是有符号的,不能用 unsigned 修饰。
- 用 typeof(数据类型) 可以确定某数据类型的字节长度。
- 命名变量名的规则:
(1)不能是C++关键字。
(2)第一个字符必须是字母或下划线。
(3)不要超过31个字符。
(4)中间不能有空格。
(5)不能包含“ . ; , " ’ + - ” 之类的特殊符号。变量名中除了能使用26个英文大小写字母和数字外,只能使用下划线“ _ ”。
(6)变量名不要与C++中的库函数名、类名和对象名相同。 - 在同一语句里不能混合定义不同类型的变量。
- typedef可以为一个已有的类型名提供一个同义词。以typedef开始,随后是要表示的类型,最后是新的类型名和分号。typedef 没有实际地定义一个新的数据类型,在建立一个typedef类型时没有分配内存空间,typedef在程序中起到帮助理解的作用。
- 八进制以0开头,十六进制以0x开头。
- 十进制数有正负之分,八进制和十六进制数只能表示无符号整数。
- 指数形式:E或e的前面必须要有数字,且E后面的指数必须为整数。
- 字符是用单引号括起来的一个字符。’ \ddd ’ 表示1 ~ 3位八进制数, ’ \xhh ’ 表示1 ~ 2位十六进制数。
例:"\x07operating\tsystem\n" 中有18个字符。 - C++中,字符串总是以’\0’结束。
- “0” 与 ‘0’ 是不同的。
- 常量名不能放在赋值语句的左边。
常量定义中初始化的值可以是一个不依赖于运行的表达式。
例:
const int size = 100 * sizeof(int);//OK
const int number = max(15,23);//ERROR - 在普通表示的输出中,setprecision(n)表示有效位数。
在确定表示的输出中,setprecision(n)表示小数位数。(用fixed)
在指数表示的输出中,setprecision(n)表示小数位数。(用scientific)
小数位数截短时,进行4舍5入处理。 - printf("%-5.3s",“Hello”);负号表示左对齐,5表示格式宽度,3表示截取字符串中3个字符。
- "%-7.2f"表示左对齐,总长度为7位,小数位2位。
- 在用"%c"格式输入时,空格字符和转义字符都作为有效字符输入。
第3章 表达式和语句
-
表达式是操作符、操作数和标点符号组成的序列,其目的是用来说明一个计算过程。
-
操作符优先级:算术运算符>关系运算符>逻辑运算符>赋值运算符
-
/ 对于整型数是取整,对于浮点数是通常意义的除法。
-
% 只能对整型数进行操作,意义为取余。
-
算术类型转换总是朝表达数据能力更强的方向,并且转换总是逐个运算符进行的。
-
数据运算过程中自动进行的类型转换称为隐式类型转换。
-
强制转换又称显示转换,其语法是在一个数值或变量前加上带括号的类型名。也可以类型名后跟带括号的数值或表达式。如果类型名是带类型修饰的,则要给类型名加括号。
-
注意||和&&的短路性。
-
条件运算符(条件表达式)?(条件为真时的表达式):(条件为假时的表达式)。条件运算符可以嵌套。
-
逗号表达式的值为第n个子表达式的值,即表达式n的值。逗号表达式还可以用于函数调用中的参数。
-
在C++中,如果逗号表达式的最后一个表达式为左值,则逗号表达式为左值。如:(a=1,b,c+1,d)=5; 即d=5
-
if ( !n ) 等价于 if ( n == 0 )
if ( n ) 等价于 if ( n != 0 )
第4章 过程化语句
- do-while循环中,while(继续条件)后面的分号不要忘记。
- for语句的三个表达式都可省略,且表达式1,2,3都可以为任何表达式。
- switch后面括号中的表达式只能是整型、字符型或枚举类型表达式。case后面的常量表达式类型必须与其匹配。
- 因为case语句起语句标号的作用,所以case与default并不改变控制流程。case常与break语句联用,以保证多路分支的正确实现。最后一个分支可以省略break语句。
- 各个case(包括default)的出现次序可以任意。在每个case分支都带有break的情况下,case次序不影响执行结果。
- 多个case可以共用一组执行语句。
- default语句是可选的。当default不出现时,则当表达式的值与所有常量表达式的值都不相等时,越过switch语句。
- switch语句可以嵌套。
- continue语句和break语句的区别是:continue语句只结束本次循环,而不是终止整个循环的执行;而break语句则是终止整个循环,不再进行条件判断。
第5章 函数
- 函数是模板化编程的最小单位。
- C++不允许函数定义嵌套,即在函数定义中再定义一个函数是非法。
- 一个程序将操作系统分配给其运行的内存块分为4个区域:代码区、全局数据区、堆区、栈区。
- 函数结束时,静态局部变量不会消失,每次该函数调用时,也不会为其重新分配空间。它始终驻留在全局数据区,直到程序运行结束。静态局部变量的初始化与全局变量类似,如果不为其显式初始化,则C++自动为其初始化为0。
- 内联函数也称内嵌函数,主要解决程序的运行效率。
- 重载函数至少在参数个数、参数类型或参数顺序上有所不同。
- typedef定义的类型只能使之相同于一个已存在的类型,而不能建立新的类型,所以不能用typedef定义的类型名来区分重载函数声明中的参数。
- C++可以给函数定义默认参数值。
- 默认参数在函数声明中提供,当又有声明又有定义时,定义中不允许默认参数。如果函数只有定义,则默认参数才可出现在函数定义中。
- 默认值可以是全局变量、全局常量,甚至是一个函数。但默认值不可以是局部变量,因为默认参数的函数调用是在编译时确定的,而局部变量的位置与值在编译时均无法确定。
- 内联函数是为了提高编程效率而实现的,它克服了用#define宏定义说带来的弊病。
第6章 程序结构
- 带extern的int n,它表明该变量n不在本文件中分配空间,而在程序的其他文件中分配空间(变量定义)。
- 带extern的变量说明是变量声明,不是变量定义。
- 默认的函数声明或定义总是extern的。
- 在全局变量前加一个static,使该变量只在这个源文件中可用,称之为全局静态变量(静态全局变量)。
- 静态全局变量对组成该程序的其他源文件是无效的。
- 第一,不必担心另外源文件使用它的名字,该名字在源文件中是唯一的。第二,源文件的全局变量不能被其他源文件所用,不能被其他源文件所修改。
- 当需要使某个函数只在一个源文件中有效,不能被其他源文件所用,这时在函数前面加上static。
- 标号是唯一具有函数作用域的标识符。goto语句使用标号。标号声明使得该标识符在一个函数内的任何位置均可以被使用。
- goto和switch语句不应使控制从一个声明的作用域跳到该声明的作用域内,因为这种跳转越过了变量的声明语句,使变量不能被初始化。
- 在内层作用域中,外层作用域声明的同名标识符是不可见的,当在内层作用域中引用这个标识符时,表示的是对内层作用域中声明的标识符的引用。
- 标识符的可见性不超过作用域,作用域则包含可见范围。
- 如果被隐藏的是全局变量,则可用符号::来引用该全局变量。
- 全局变量、静态全局变量、静态局部变量都具有静态生命期。具有文件作用域的变量具有静态生命期。静态生命期的变量,若无显示初始化,则自动初始化为0。
- 在函数内部声明的变量或是块中声明的变量具有局部生命期。具有局部作用域的变量若为局部变量,则具有局部生命期,若为静态局部变量,则有静态生命期。具有局部生命期的变量驻在内存的栈区。具有局部生命期的变量若未初始化,则内容不可知。
- 三类编译预处理指令:#include,#define,#if。
- #include包含指令:让预处理器把一个源文件嵌入到当前文件中该点处。
- #define宏定义指令:建立常量,定义带参数的宏,还有一个有效的使用是在条件编译指令中。
- 条件编译指令有:#if,#else,#elif,#endif,#ifdef,#ifndef,#undef。
- 条件编译的一个有效使用时协调多个头文件。使用#undef可以取消符号定义,这样可以根据需要打开和关闭符号。
第7章 数组
- 数组是一个由若干同类型变量组成的集合。
- 下标是数组元素到数组开始的偏移量。
- 在编译时,数组定义中的下标必须确定。用全局变量的值来确定数组下标也是不允许的。
- 初始化数组的值的个数不能多于数组元素个数,初始化数组的值也不能通过跳过逗号的方式来省略。
- 初始化值的个数可少于数组元素个数。当初始化值的个数少于数组元素个数时,前面的按序初始化相应值,后面的初始化为0。
- 初始化表值{1}表示第1个元素的值,而不是指全部数组元素都为1。
- 有初始化的数组定义可以省略方括号中的数组大小。
- 对于字符串的初始化,要注意数组实际分配的空间大小事字符串个数加上末尾的’\0’结束符。
- 数组的大小为n,而字符串的长度为n-1。
- 将数组作为参数传给函数,实际上只是把数组的地址传给函数。
- 如果对全部元素都赋初始值,则定义数组时对第一维的大小可以忽略,但第二维的大小不能省。
- 在定义时,也可以只对部分元素赋初始值而省略第一维的大小,但应分行赋初始值。
- 函数调用时,数组参数的实参为整型变量的地址;函数原型中,数组参数的形参为整型数组的首地址。
- 有一种从数组尾部跳到其头部的技巧是“加1求模”。
第8章 指针
- 在指针定义中,一个*只能表示一个指针。
- 用&操作可以获取变量的地址,指针变量用于存放地址。
- 间接引用指针时,可获得由该指针指向的变量内容。
- *放在可执行语句中的指针之前,称为间接引用操作符,而其放在指针定义中时,称指针定义符。
- 非指针变量是不能用间接引用操作符的,因为*只能作用于地址。
- 间接引用既可以用于右值,也可以用于左值。
- 指针变量初始化的值是该指针类型的地址值。
- 指针在使用前,要进行初始化。指针忘赋值比整形变量忘了赋值要危险的多。
- 指针iPtr++不是后移一位,而是后移了一个单位。
- 只有加法和减法可用于指针运算。
- a[i] 等价于 * (a+i) 等价于 iPtr[i] 等价于 * (iPtr+i)
- &a[i] 等价于 a+i 等价于 iPtr+i 等价于 &iPtr[i]
- 数组名本身是一指针,它的类型是指向数组元素的指针。
- 数组名是指针常量,区别于指针变量。所以给数组名赋值是错误的。
- 常量指针(指向常量的指针):在指针定义语句的类型前加const,表示指向的对象是常量。定义指向常量的指针只限制指针的间接访问操作,而不能规定指针指向的值本身的操作规定性。const int * pi = &a;不能通过*pi来修改a的值,但可以把pi指向另外一个变量。
- 指针常量:在指针定义语句的指针名前加const,表示指针本身是常量。在定义指针常量时必须初始化。char * const pc = “asdf”;可以通过 * pc来修改其内容,但不能改变指针值即指向另外一个变量。
- 常量指针常量(指向常量的指针常量):const int * const cpc = &b;其中cpc和 * cpc都是常量,不能作为左值进行操作。
- 声明Sum( int array[], int n )和Sum( int * array, int n )是等价的。
- 传递指针的函数调用实现过程为:一,函数声明中指明指针参数,例void swap( int * x, in * y );二,函数调用中传递以变量的地址,例swap( &a, &b );三,函数定义中对形参进行间接访问。
- 返回指针的函数称为指针函数。指针函数不能把在它内部说明的具有局部作用域的数据地址作为返回值。
- 由于字符串的地址属性,所以两个同样字符组成的字符串的地址是不相等的。例,不能写if( “join” == “join” ),而要用strcmp()。
- 字符串,字符数组名,字符指针均属于同一种数据类型。输出字符指针就是输出字符串。输出字符指针的间接引用,就是输出单个字符。
- 两个字符串的比较是地址的比较,两个数组名的比较也是地址的比较。如果要进行字符串比较用strcmp(str1,str2);当str1>str2,返回正值;当str1<str2,返回负值;当str1=str2,返回0。
- 指针数组:一个数组中每个元素都是一个指针。char * proname[] = { “Fortran”, “C”, “C++” };
- 指针数组与二维数组是有区别的。字符指针数组的内存表示,指针所指向的字符串是不规则长度的。二维数组每一列的大小必须是一样的。
- 指针数组名是指向指针的指针(即二级指针)。
- 传递数组给函数就是传递指针给函数。传递指针数组给函数就是传递二级指针给函数。
- NULL与void * 是不同的概念,NULL是一个值,一个指针值,任何类型的指针都可赋予该值。而void * 是一种类型,是一种无任何类型的指针。
- 函数指针:int ( * func )( char a, char b );
第9章 引用
- 引用不是值,不占存储空间,声明引用时,目标的存储状态不会改变。引用只有声明,没有定义。
- 引用运算符只在声明的时候使用,它放在类型名后面。任何其他“&”的使用都是地址操作符。
- 为了提高可读性,不应在同一行上同时声明引用、指针和变量。
- 如果程序寻找引用的地址,它只能找到所引用的目标的地址。
- 建立引用时必须进行初始化并且绝不会再指向其他不同的变量。
- 指针也是变量,可以有指针变量的引用。int * a;int * & p = a;//表示int * 的引用p初始化为a。
- 对void进行引用是不允许的。
- 不能建立引用的数组。
- 引用本身不是一种数据类型,所以没有引用的引用,也没有引用的指针。
- 引用不能用类型来初始化。有空指针,无空引用。
- 保护实参不被修改的办法是传递const指针和引用。
第10章 结构
- 声明一个结构并不分配内存,内存分配发生在定义这个新数据类型的变量中。
- 在数组中,数组是不能彼此赋值的。两个不同结构名的变量是不允许相互赋值的,即使两者包含同样的成员。但两个相同结构名的变量是可以相互赋值的。
- 结构变量不是指针,通过取地址“&”操作,可以得到结构变量的地址,这个地址就是结构的第一个成员地址。
- prPtr->name 等价于 pr1.name 等价于 (*prPtr).name
- 结构数组中,每个元素都是结构变量。
- 一个函数可以返回一个结构的引用和结构的指针,但是不要返回一个局部结构变量的引用或指针。
- 结构可以嵌套,即结构中可以包含结构成员。在引用嵌套结构的成员时,要使用多个点操作符。
- 结构成员不能是自身的结构变量,但可以是自身结构指针作为成员。
第11章 类
- C++特点:抽象、封装、继承、多态。
- ::叫作用域区分符,指明一个函数属于哪个类或一个数据属于哪个类。::可以不跟类名,表示全局数据或全局函数(即非成员函数)。
- 不能对类的数据成员进行初始化。
- 由于类名是成员函数名的一部分,所以一个类的成员函数与另一个类的成员函数即使同名,也不能认为是重载。
- 成员函数必须用对象来调用。
- 一个类对象所占据的内存空间由它的数据成员所占据的空间总和说决定。类的成员函数不占据对象的内存空间。
- 类的作用域是指类定义和相应的成员函数定义范围。
- 如果一个非类型名隐藏了类型名,则类型名通过加前缀可用。如果一个类型名隐藏了一个非类型名,则用一般作用域规则即可。
- C++规定,一个名字不能同时指两种类型。非类型名(变量名、常量名、函数名、对象名或枚举成员)不能重名。
第12章 构造函数
- C++规定与类同名的成员函数是构造函数,在该类的对象创建时,自动被调用。
- 构造函数没有返回类型,函数体中也不允许返回值,但可以有无值返回语句“return;”。
- 一个类定义中,类的数据成员可能为另一个类的对象。
- 如果一个类对象是另一个类的数据成员,则在那个类的创建所调用的构造函数中,对该成员(对象)自动调用其构造函数。
- 析构函数没有返回类型,没有参数,没有重载。只是在类对象生命期结束的时候,由系统自动调用。
- 析构函数以调用构造函数相反的顺序被调用。
- 无参的构造函数被称为默认构造函数。
- C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。
- 若未提供一个类的构造函数(一个都未提供),则C++提供一个默认的构造函数,该默认构造函数是个无参构造函数,它负责创建对象,而不做任何初始化工作。
- 只要一个类定义了一个构造函数(不一定是无参构造函数),C++就不再提供默认的构造函数。即如果为类定义了一个带参数的构造函数,还想要无参构造函数,则需要自己定义。
- 与变量定义类似,在用默认构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的位模式全为0,否则,对象值是随机的。
- 类是一个抽象的概念,并不是一个实体,并不含有属性值,而只有对象才占有一定的空间,含有明确的属性值。
- 冒号语法使得常量数据成员和引用数据成员的初始化成为可能。
- 常量和引用的初始化必须放在构造函数正在建立数据成员结构的时候,也就是放在构造函数的冒号后面。
- 对于类的数据成员是一般变量的情况,则放在冒号后面与放在函数体中初始化都一样。
- 创建对象的唯一途径是调用构造函数。
- 静态对象和静态变量一样,文件作用域的静态对象在主函数开始运行前全部构造完毕。块作用域中的静态对象,则在首次进入到定义该静态对象的函数时,进行构造。
- 多有全局对象都在主函数main()之前被构造。
- 成员以其在类中声明的顺序构造。
第14章 堆与拷贝构造函数
- 全局变量、静态数据、常量存放在全局数据区,所有类成员函数和非成员函数代码存放在代码区,为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区,余下的空间都被作为堆区。
- 从堆上分配对象数组,只能调用默认的构造函数,不能调用其它任何构造函数。如果该类没有默认构造函数,则不能分配对象数组。
- delete[]pS中的[]是要告诉C++,该指针指向的是一个数组。如果在[]中填上了数组的长度信息,C++编译系统将忽略,并把它作为[]对待。但如果忘了写[],则程序将会产生运行错误。
- 如果你的类需要析构函数来析构资源,则它也需要一个拷贝构造函数。
- 可以直接调用构造函数产生无名对象。无名对象可以作为实参传递给函数,可以拿来拷贝构造一个新对象,也可以初始化一个引用的声明。
- 转换构造函数是定义含一个参数的构造函数。
- 运算符new分配堆内存,如果成功,则返回该内存的空间,如果失败,则返回NULL。所以每次使用运算符new动态分配内存时,都应测试new的返回指针值,以防分配失败。pName = new char[ strlen(pN) + 1 ];if ( pName != 0 ) strcpy( pName, pN );
第15章 静态成员与友元
- 声明为static的类成员便能在类范围中共存,称之为静态成员。
- 静态数据成员在类声明外分配空间和初始化。
- 调用静态成员函数用类名引导。
- 公共静态数据成员可被类的外部访问,保护或私有静态数据成员只可被类的内部访问。
- 静态成员函数定义是类的内部实现,属于类定义的一部分。它的定义位置与一般成员函数一样。
- 一个静态成员函数不与任何对象相联系,故不能对非静态成员进行默认访问。
- 静态成员函数与非静态成员函数的根本区别:静态成员函数没有this指针,而非静态成员函数有一个指向当前对象的指针this。
- 在类里申明一个普通函数,标上关键字friend,就成了该类的友元,可以访问该类的一切成员。
- 友元声明的位置可在类的任何部位,既可以在public区,也可以在protected区,意义完全一样。友元函数定义则在类的外部,一般与类的成员函数定义放在一起。
- 一个类的成员函数可以是另一个类的友元。
- 整个类可以是另一个类的友元,该友元称为友类。友类的每个成员函数都可以访问另一个类中的保护或私有数据成员。
- 静态成员的static一词与静态存储类的static是两个概念,一个论及类,一个论及内存空间的位置以及作用域限定。所以要区分静态对象和静态成员。
第17章 多重继承
- 虚拟继承的虚拟和虚拟函数的虚拟没有任何关系。
- 多继承的构造顺序:一,任何虚拟基类的构造函数按照它们被继承的顺序构造。二,任何非虚拟基类的构造函数按照它们被继承的顺序构造。三,任何成员对象的构造函数按照它们声明的顺序调用。四,类自己的构造函数。
- 在继承关系中,基类的private成员不但对应用程序隐藏,甚至对派生类也隐藏。而基类的保护成员则只对应用程序隐藏,而对派生类则毫不隐瞒。
- 一个私有的或保护的派生类不是子类,因为非公共的派生类不能做基类能做的所有的事。
- 保护继承与私有继承类似,继承之后的类相对于基类来说是独立的。保护继承的类对象,在公开场合同样不能使用基类的成员。
- 当一个类是两个或多个基类的派生类时,必须在派生类名和冒号之后,列出所有基类的类名,基类间用逗号隔开。
- 派生类的构造函数必须激活所有基类的构造函数,并把相应的参数传递给它们。
- 在无继承的类中,protected和private控制符是没有差别的。在继承中,基类的private对所有的外界都屏蔽(包括自己的派生类),基类的protected控制符对应用程序是屏蔽的,但对其派生类是可访问的。
第18章 运算符重载
- 运算符是函数,除了运算顺序和优先级不能更改外,参数和返回类型是可以重新说明的,即可以重载。
- C++规定了“ . 、:: 、. * 、-> 、?: ”这五个运算符不能重载,也不能创造新运算符。
- operator++()是单目运算符,它含有一个参数。++d <=> d.operator++(); d++ <=> d.operator++(0)
- C++规定: =,(),[ ],-> 这四种运算符必须为成员形式。
- 使用前增量,对对象(操作数)进行增量修改,然后再返回该对象。所以前增量运算符操作时,参数与返回的是同一对象。
- 使用后增量,必须在增量之前返回原有的对象值。为此,要创建一个临时对象,存放原有的对象,以便操作数(对象)进行增量修改时,保存最初的值。
- 转换运算符:operator 类型名();它没有返回类型,因为类型名就代表了它的返回类型,故返回类型显得多余。
- 转换运算符与转换构造函数(简称转换函数)互逆。
平时作业易错题
- 实现运行时的多态性采用(D)
A. 重载函数
B. 构造函数
C. 析构函数
D. 虚函数 - 虚基类是用来解决多继承中公共基类在派生类中只产生一个基类子对象的问题。(正确)
- 打开ASCII码流文件和二进制流文件时,打开方式是相同的。(错误)
- 派生类的构造函数一般有3项工作要完成:首先基类初始化,其次成员对象初始化,最后执行派生类构造函数体。(正确)
- 面向对象程序设计有四个主要特点,即抽象、封装、继承和多态。
- 若派生类执行无参构造函数,则其基类也将调用无参构造函数,即基类必须定义有无参构造函数。(错误)
解析:基类可能有默认构造函数(即无参构造函数),所以不一定需要定义。 - 以app方式打开文件时,当前的读指针和写指针都定位于文件尾。(正确)
- 作用域运算符“::”的功能是(B)
A. 标识作用域的级别的
B. 指出作用域的范围的
C. 给定作用域的大小的
D. 标识成员是属于哪个类的 - 关于const关键字说法错误的是(D)
A. const关键字可以修饰对象和成员函数
B. const对象不能被修改
C. const成员函数不能修改类数据成员
D. const可以用于说明类 - 下列描述错误的是(A)
A. 在创建对象前,静态成员不存在
B. 静态成员是类的成员
C. 静态成员不能是虚函数
D. 静态成员函数不能直接访问非静态成员 - 每个类有且仅有一个拷贝构造函数。(错误)
解析:一个类至少有一个拷贝构造函数;事实上,可以有多个。 - 友元函数是用关键字friend修饰的成员函数。(错误)
解析:友元函数不是成员函数。 - 已知:m是类A的对象,n是类A的公有数据成员,p是指向类A中n成员的指针。则这两种表示是等价的:m.n和m.*p。(正确)
- 对象数组的元素可以是不同类的对象。(错误)
- 假定AB为一个类,则执行AB a(2),b[3],*p[4]; 语句时调用该类的构造函数的次数是(B)
A. 3
B. 4
C. 5
D. 9 - 关于this指针使用说法正确的是(A)
A. 保证每个对象拥有自己的数据成员,但共享处理这些数据的代码。
B. 保证基类私有成员在子类中可以被访问。
C. 保证基类保护成员在子类中可以被访问。
D. 保证基类公有成员在子类中可以被访问。 - 类的实例化是指(B)
A.定义类
B.创建类的对象
C.指明具体类
D.调用类的成员 - 关于对象概念的描述中,说法错误的是(A)
A. 对象就是C语言中的结构变量
B. 对象代表着正在创建的系统中的一个实体
C. 对象是类的一个变量
D. 对象之间的信息传递是通过消息进行的 - 下列不能作为类的成员的是 (B)
A. 自身类对象的指针
B. 自身类对象
C. 自身类对象的引用
D. 另一个类的对象 - 若有说明: char *language[ ] = {“FORTRAN”, “BASIC”, “PASCAL”, “JAVA”, “C”};则表达式 *language[1] > *language[3] 比较的是(C)
A. 字符F和字符P
B. 字符串BASIC和字符串JAVA
C. 字符B和字符J
D. 字符串FORTRAN和字符串PASCAL - 若有定义:int c[5], *p=c;,则以下正确的表达式是(C)
A. c++
B. p+5
C. &c[0]
D. &c+1 - 设有以下说明语句,则下面的叙述不正确的是(D)
struct abc
{
int m;
float n;
} stype;
A. stype是用户定义的结构体变量名
B. m和n都是结构体成员名
C. struct是结构体类型的关键字
D. stype是用户定义的结构体类型名 - C++语言结构体类型变量在程序执行期间(C)
A. 只有一个成员驻留在内存中
B. 部分成员驻留在内存中
C. 所有成员一直驻留在内存中
D. 没有成员驻留在内存中 - 下面关于结构体概念的叙述中,正确的说法是(D)
A. 整数的集合称为结构体
B. 相同类型数据的集合称为结构体
C. 数据的集合称为结构体
D. 不同类型数据的集合称为结构 - 以下字符串赋值的表达式中,不能正确赋值的是(D)
A. char s[10] = {‘c’,‘h’,‘i’,‘n’,‘a’,’\0’};
B. char *s = “china” ;
C. char s[ ] = “china”;
D. char s[10]; s = “china”; - 在基本数据类型相同的两个指针变量之间,不能进行的运算是(A)
A. +
B. <
C. =
D. -
解析:B选项两个同类型的指针间可以比较大小,比较原则应该是按照实际内存的高低位比较的。C选项赋值,这个当然是可以的了。D选项两个相同指针变量相减可以获得在之间相隔的同类型元素个数(在某个类型的数组中的应用)。A选项是不可以的,因为两个指针相加什么都得不到,所以规定不允许相加。 - 下面能正确进行字符串赋值,并且能确保字符串以’\0’;结尾的操作是(C)
(A) char s[5] = {“ABCDE”};
(B) char s[5] = {‘A’,‘B’,‘C’,‘D’,‘E’};
(C) char *s; s = “ABCDE”;
(D) char *s; scanf("%s", s);
解析:A:错误。ABCDE是一个字符串,本身最后以’\0’,赋值给s,会写溢出。但是s[4]是’E’结尾,不是’\0’。
B:同上,但是不会溢出。s[4] 是’E’
C:“ABCDE”最后是’\0’,首地址赋值给s,s指向的字符串就是"ABCDE",结尾自然是’\0’。
D:程序错误。s没有申请内存空间,并且首次定义s中的数据为不确定的,直接输入,会将数据写入非法的内存区域。 - 在C++语言中,调用函数时,下列说法正确的是 (D)
(A) 实参占有独立的存储单元,形参不占存储单元。
(B) 实参和形参必须共用存储单元。
(C) 实参和形参是否共用存储单元由用户指定。
(D) 实参和形参各自占有独立的存储单元。 - 结构化程序设计的三种基本结构是顺序结构、选择结构、循环结构。
- 字符串常量“123”在内存中的字节数是4。
- 在C/C++语言中,八进制整型常量以0作为前缀。
- 已知x,y为整型,z为实型,ch为字符型,则下列表达式中正确的是(B)
A. z=(x+y)++
B. y=ch+x
C. x+y=z
D. y=z%x
解析:A,实型的精度比整型高,可以接受整型的结果,但是++是整型变量的自增运算,相当于赋值运算,显然有错误。
C,x+y= z显然是错误的,赋值运算符的使用错误
D,%是整型数据的运算符,D错误 - 在C++语言中的if语句中,用作判断的表达式为(D)
A.关系表达式
B.逻辑表达式
C.算术表达式
D.任意表达式 - 执行语句printf("%o",-1);后屏幕的显示为(C)
A. -1
B. 1
C. 177777
D. -177777
备注:请查阅负数的原码、反码、补码,弄清楚负数的存储形式。此题int占2个字节。