Q 31 :
题目:
分析一下这段程序的输出:
#include<iostream>
using namespace std;
class B{
public:
B(){
cout << "default constructor" << " ";
}
~B(){
cout << "destructed" << " ";
}
B(int i):data(i){
cout << "constructed by parameter" << data << " ";
}
private:
int data;
};
B Play(B b){
return b;
}
int main(int argc, char *argv[]){
B temp = Play(5);
return 0;
}
答案:
constructed by parameter5
destructed
destructed
解答:
考察赋值运算顺序以及拷贝构造函数。
1. B temp = Play(5)从右向左执行。
2. 先将"5"转为形式参数B的类型,之后调用B(int i)打印
"constructed by parameter"。
4. B temp调用B的默认浅拷贝构造函数,完成赋值,由于拷贝构
造函数没有输出,所以没有打印东西。
6. Play()生命周期结束后,b析构打印"destructed"。
7. main()生命周期结束后,temp析构打印"destructed"。
Q 32 :
题目:
int i=10, j=10, k=3;
k*=i+j;
k最后的值是?
答案:
60
解答:
考察运算符优先级。
1. +优先级高于*=,等价于k = k * (i +j)。
Q 33 :
题目:
#include命令的功能是:
答案:
在命令处插入一个文本文件
解答:
1. "#include"在命令处插入,插入文本过程为预处理过程。
Q 34 :
题目:
有一个类A,其数据成员如下:
class A {
private:
int a;
public:
const int b;
float* &c;
static const char* d;
static double* e;
};
则构造函数中,成员变量一定要通过初始化列表来初始化的是:
答案:
b
c
解答:
考察构造函数初始化列表的使用。
构造函数中,成员变量一定要通过初始化列表来初始化的有以
下几种情况:
const常量成员:因为常量只能在初始化,不能赋值,所以必
须放在初始化列表中。
引用类型:引用必须在定义的时候初始化,并且不能重新赋值,
所以也要写在初始化列表中。
没有默认构造函数的类类型:因为使用初始化列表可以不必
调用默认构造函数来初始化,而是直接调用拷贝构造函数。
Q 35 :
题目:
在一个64位的操作系统中定义如下结构体:
struct st_task{
uint16_t id;
uint32_t value;
uint64_t timestamp;
};
同时定义fool函数如下:
void fool(){
st_task task = {};
uint64_t a = 0x00010001;
memcpy(&task, &a, sizeof(uint64_t));
printf("%11u, %11u, %11u", task.id,
task.value, task.timestamp);
}
上述fool()程序的执行结果为:
答案:
1
0
0
解答:
考察结构体对齐。
1. 假设低地址在低位,最低16 bits被赋给低16位的id变量。
2. 接下来16 bits的0x0001部分被赋值给了pading部分,没有被使用。
3. value和timestamp均未被赋值。
Q 36 :
题目:
在32位系统中:
char arr[] = {4, 3, 9, 9, 2, 0, 1, 5};
char *str = arr;
sizeof(arr) = (1);
sizeof(str) = (2);
strlen(str) = (3);
答案:
8;4;5
解答:
考察指针和数组名使用sizeof时区别及转义字符。
1. 数字0对应'\0'。
2. strlen求字符串长到'\0'前。
Q 37 :
题目:
下面代码输出什么:
#include<stdio.h>
int main( ){
unsigned int a = 6;
int b = -20;
(a + b > 6) ? printf(">6") : printf("<=6");
return 0;
}
答案:
>6
解答:
考察强制类型转换。
1. 必须先明确:int与unsigned相加,int -> unsigned int。
2. int b = -20,首位位"1",用无符号型表示是非常大的正整数。
Q 38 :
题目:
对于下面的C语言声明描述正确的一项是:
char (*p)[16]
答案:
p是指向长度为16的字符数组的指针
解答:
考察运算符优先级。
1. p先和那个运算符结合就是什么。
2. char *p[16]:p是一个包含16个元素的Char型指针数组,
[]优于*,p[]先结合,是数组。
3. char (*p)[16]:p是一个指针,指向一个包含16个元素的
char数组,由于()出现,先和*结合,是指针。
[Q 39]
题目:
下面程序输出结果是什么:
#include<iostream>
using namespace std;
class A{
public:
A(char *s){
cout << s << endl;
}
~A(){}
};
class B:virtual public A{
public:
B(char *s1, char*s2):A(s1){
cout << s2 << endl;
}
};
class C:virtual public A{
public:
C(char *s1, char*s2):A(s1){
cout << s2 << endl;
}
};
class D:public B, public C{
public:
D(char *s1, char *s2, char *s3, char *s4):
B(s1, s2), C(s1, s3), A(s1){
cout << s4 << endl;
}
};
int main() {
D *p = new D("class A", "class B", "class C",
"class D");
delete p;
return 0;
}
答案:
class A
class B
class C
class D
解答:
考察虚继承的继承顺序。
1. class B, class C为虚继承。
2. 虚继承(class 派生类:virtual 继承方式 基类名):从不
同的路径继承过来的同名数据成员在内存中就只有一个拷贝。
3. 继承顺序:
执行基类构造函数,多个基类的构造函数按照被继承的顺序构
造。
执行成员对象的构造函数,多个成员对象的构造函数按照声明的顺序构造。
执行派生类自己的构造函数。
4. 要执行D构造函数必须先执行参数列表,欲构造B, C必须先构
造A,其B, C虚继承A,所以只要执行一次构造函数。
Q 40 :
题目:
如下程序段:
char a[] = "xyz", b[] = {'x', 'y', 'z'};
if(strlen(a) > strlen(b))
printf("a > b\n");
else
printf("a <= b\n");
则程序输出:
答案:
a<=b
解答:
考察对strlen实现的理解。
1. strlen函数判断字符串长仅仅是通过字符串末的'\0'(字符0)来确定。
2. 数组b为标识具体'\0'位置,所以使用strlen结果至少大于等于3。
Q 41 :
题目:
执行以下语句,输出结果为:
char *p1 = "hello";
char *p2 = "world";
char *p3 = "a piece of cake";
char *str[] = {p1, p2, p3};
printf("%c", *(str[0] + 1));
答案:
e
解答:
考察指针、指针函数及其操作。
1. str是指针数组,每个元素都是指针。str[0]代表的是
char *类型指针p1。
2. p1是char *类型,只想字符串"hello",所以这里“+1”代表
以字符为单位,结果为'e'。
[Q 42]
题目:
以下表达式那些会被编译器禁止:
int a = 248, b = 4;
int const c = 21;
const int *d = &a;
int *const e = &b;
int const * const f = &a;
答案:
*c = 32
*d = 43
e = &a
f = 0x321f
解答:
考察指针常量、常量指针。
1. 区分是指针的值不会变还是指针指向的变量值不会变。
2. 方法:
如果 const 位于 * 的左侧,则 const 就是用来修饰指
针所指向的变量,即指针指向为常量。
如果 const 位于 * 的右侧, const 就是修饰指针本身,
即指针本身是常量。
3. 方法使用:
int const c -> 变量c的值不可改变。
const int *d -> const在*左(离指针远),修饰指向
的变量 -> 指针d指向的变量不可变。
int *const e-> const在*右(例指针近),修饰指针
-> 指针e的值不可变。
int const * const f -> 有左有右 -> 值和指针均不可变。
Q 43 :
题目:
以下描述正确的是:
答案:
虚函数不能是内联函数
父类的析构函数是非虚的,但是子类的析构函数是虚的,delete
子类对象指针会调用父类的析构函数
解答:
1. 虚函数不能是内联函数(编译时展开,必须有实体),不能是
静态函数(属于自身类,不属于对象,而虚函数要求有实体),不
能是构造函数(尚未建立虚函数表)。
2. delete子类对象是一定会调用父类的析构函数的先调用子类的
析构函数然后调用父类的析构函数。
Q 44 :
题目:
class Base{
public:
Base(){
Init();
}
virtual void Init(){
printf("Base Init\n");
}
void func(){
printf("Base func\n");
}
};
class Derived: public Base{
public:
virtual void Init(){
printf("Derived Init\n");
}
void func(){
printf("Derived func\n");
}
};
int main(){
Derived d;
((Base *)&d)->func();
return 0;
}
答案:
Base Init
Base func
解答:
考察虚函数。
1. 类Derived继承自Base,先调用基类构造函数Base(),再调
用基类的init(),输出Base Init。
构造子类对象,基类中不会调用子类的虚函数:
基类构造函数 -> 子类构造函数
子类还没有构造,还没有初始化,属于未初始化对象
基类不会去调用子类虚函数(哪怕子类中确实声明为虚函数)
2. 虽然 ((Base *)&d)->func()是虚函数调用的样子,但
func()跟本没有被定义为虚函数,基类指针访问基类的func()。
Q 45 :
题目:
采用多路复用I/O监听3个套接字的数据时,如果套接字描述符分别
是:5,17,19,则:
select(int maxfd, struct fd_set* rdset, NULL, NULL)
中的maxfd应取为:
答案:
20
解答:
1. maxfd是三个套接字描述符中最大数字加上1。