大众点评试题分析(C/C++)
1.main函数执行完毕,从栈中弹出操作函数
void fn1(void), fn2(void), fn3(void); int main() { atexit(fn3); atexit(fn1); atexit(fn2); cout << "hello world" << endl; //检测内存泄漏 _CrtDumpMemoryLeaks(); return 0; } void fn1() { cout << "A" << endl; } void fn2() { cout << "B" << endl; } void fn3() { cin.get(); }
执行代码效果为:
hello world
B
A
具体解释可以参考:http://www.cnblogs.com/wxxweb/archive/2011/05/25/2055696.html
2.为了取代C中带参数的宏,C++中使用内联函数代替,类似宏直接将相应代码插入。
我原本还以为是模板,因为宏忽略类型检查,模板在一定程度上适应多种类型。
3.关于多层继承的虚基类
class A { public: A(const char *s) { cout << s << endl;// ~A() {} } }; class B : virtual public A { public: B(const char *s1, const char *s2) :A(s1) { cout << s2 << endl; } }; class C : virtual public A { public: C(const char *s1, const char *s2) :A(s1) { cout << s2 << endl; } }; class D : public C,public B { public: D(const char *s1, const char *s2, const char *s3, const char *s4) :C(s1, s3), B(s1, s2), A(s1) { cout << s4 << endl; } };
void main() { D *ptr = new D("class A", "class B", "class C", "class D"); delete ptr; ptr = NULL; }
输出结果为:A,C,B,D。相关理论解释可以参考:http://blog.csdn.net/lovemysea/article/details/5298853
Ps:C++ primer上总结:可以使用一个数组来表示多种类型的对象,这就是多态性。
Ps:为何积累需要使用虚析构函数:
如果函数不是虚的,则将只调用对应于指针类型的析构函数。
如果是基类指针指向派生类,析构函数不为虚的话,则只会调用基类析构函数,而派生类的析构函数不会被调用。
Ps:创建派生类对象时,比需调用派生类的构造函数。然而,派生类的构造函数通常使用成员初始化列表来调用基类构造函数,以创建派生对象的基类部分。
如果派生类构造函数没有使用成员初始化列表显示调用及类构造函数,将使用基类的默认构造函数。
在继承链中,每个类都可以使用成员初始化列表将信息传递给相邻的基类。
3.递归次数计算:
int fib(int n) { if (0 == n) return 1; if (1 == n) return 2; return fib(n - 1) + fib(n - 2); }
诸如此类计算递归调用次数,此处可以分解为N[fib(n)]=N[fib(n-1)]+N[fib(n-2)]+1,N表示调用次数。
4.运算符优先级(可能是一个常考点)
struct num { int x; int y; }sa[] = { {2,32},{8,16},{4,48} }; num *p = sa + 1; int x = p->y / sa[0].x*++p->x; cout << x << " " << p->x << endl;
此处,需注意x赋值表达式是按照从左向右执行,即先执行
p->y / sa[0].x
后续问题在于是(++p)->x || ++(p->x)
此处->运算符优先级高于前置++,故是先结合p->x,再执行++操作。
相关可以参考:http://blog.csdn.net/sxhelijian/article/details/17276879
5.递归调用:
int test(int m, int n) { if (0 == m) return n + 1; if (0 == n) return test(m - 1, 1); return test(m - 1, test(m, n - 1)); }
此题只知答案为9,快捷做法暂不清楚。
6.不合法表达式:
int n = 3; double m = 3.2; (m + n) | n; m << 2; !m *= n;
三个表达式皆为不合法的,其中一二项不是整数或者是未区分范围的整形,第三项是表达式必须是可修改的左值。
7.printf参数:
int a = 123, b = 456; printf("%d\n", a, b);
输出:123。
此处输出参数仅为一个,参数列表中有两个亦无妨输出。
如果改为%f,输出0.0000。
8.数组正确初始化:
char a[] = { 0,1,2,3,4 };
正确,%d是数字,%c是对应的ASCII码。我好蠢啊。
9.数组指针和指针数组:
int a[2][3] = { {1,2,3},{4,5,6} }; int m, *p=&a[0][0]; m = (*p)*(*(p + 2))*(*(p + 4));
此处*(p+2)指p[2]。
声明指针数组应该如此
int (*ptr)[3] = a; cout << **ptr << " " << **(ptr + 1) << " " << *(*ptr + 1) << " " << *(ptr[1]) << endl;
输出为:1 4 2 4.
10.异常:(现阶段尚未复习)
class A { public: A() {} ~A() { cout << "S" << endl; } }; char fun0() { A a; throw('T'); return '0'; } int main() { try { cout << fun0() << endl; } catch (char c) { cout << c << endl; } }
输出结果为:S T。我大概了解了。
11.预处理命令:
以下叙述中正确的是( )。
A.预处理命令行必须位于源文件的开头
B.在源文件的一行上可以有多条预处理命令
C.宏名必须用大写字母表示
D.宏替换不占用程序的运行时间
D正确,编译期间已经进行了替换。预处理命令行可以出现在源文件的任意一行
12.转义字符:
‘\\':代表一个单引号(撇号)字符;'\"' :代表一个双引号字符。
'\081'表示八进制数字,注意前面使用0表示为八进制。
13.scanf使用:
char a, b, c, d; scanf("%c%c%d%d", &a, &b, &c, &d); printf("%c,%c,%d,%d",a,b,c,d);
这里输入数字会出现错误输出,主要是c、d为char型,却使用%d,这样会导致错误的取值。
14.下列各组的变量中,含义相同的一组是:(A)
A:signed short int 和 short
B:short int 和 int
C:unsigned short int 和 int
D:unsigned long int 和 long
15.字符串长度:。。。老调重弹还错
char a[] = "xyz", b[] = { 'x','y','z' }; cout << sizeof(a) <<" "<< sizeof(b) << endl;
答案是4 3。。。
16.表达式执行顺序
int j, k, l, m; int i = (j = 4, k = 8, l = 16, m = 32); cout << i << endl;
答案为32
17.enum数值
enum A { a1,a2,a3,a4,a5 }; cout << a1 << endl;
输出结果:0。
初始值为0,这么简单还错。。。
蛮好玩的,第一次做题库,感觉刷的挺爽的,就是结果出来不爽。
截一张图纪念一下自己渣渣的水平。