get c++的 面试 题
1.构造函数、析构函数和虚函数的调用顺序
class base { virtual void method() { cout<<"from base"<运行结果:
2.函数返回指针
int* fun(int a[]) { static int c[10];//c++ 允许您从函数返回指针,但是,c++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量;你可以试试去掉static for(int i=0;i<5;i++) c[i]=a[i]; return c; } int main() { int d[6]={1,3,2,5,4}; int* c=fun(d); for(int i=0;i<5;i++) cout<<*(c+i)<<" "; cout<;>
运行结果:
3.指针,指针数组的使用
int main() { char *p[1]={"hello"}; printf("%s\n",(p)[0]); int as[5]={1,2,3,4,5}; int *ptr=(int*)(&as+1); printf("%d,%d\n",*as+1,*(ptr-1)); }运行结果:
4.char类型赋值int型,输出%d格式(小于128的数值,直接隐式转换为相应数字,不小于128的数字输出其对应的值对128取余再加-128)
int main() { char a,b,c,d; a=127,b=128,c=197,d=500; //b=128%128+(-128),c=197%128+(-128)...... printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d); return 0; }运行结果:
5.无符号整形(负数时转换:2^32-(负数))
int main() { cout<<(25u-50)<;>运行结果:
6.\r \n 的使用:
'\n'是新行键,光标换到下一行;'\r'是回车键,光标移动到本行最左端位置,后边如果还有字符就会从首位开始覆盖
int main() { printf("crazefor\rcode\n"); printf("abcd\r123\n"); printf("123\r456\r789\n"); printf("cat\rdog\n"); printf("123\n456\n789\r"); return 0; }运行结果:
7.字符数组和字符指针的比较
int main() { char cc[20]="hello,world"; char dd[20]="hello,world"; cout<<(cc==dd)<;>运行结果:
8.throw 异常
class a{ public: a(){} ~a(){ cout<<"destory a"<;>运行结果:
(i)、程序接受到throw语句后就会自动调用析构器,把该域(try后的括号内)对象clean up,然后再进 入catch语句(如果在循环体中就退出循环)。
这种机制会引起一些致命的错误,比如,当“类”有指针成员变量时(又是指针!),在 “类的构建器 ”中的throw语句引起的退出,会导致这个指针所指向的对象没有被析构。这里很基础,就不深入了,提 示一下,把指针改为类就行了,比如模板类来代替指针,在模板类的内部设置一个析构函数。
9.==和前置++、后置++的优先级(先单目后双目运算符)
int main() { int a=10; if(a==a--) printf("true1\n"); a=10; if(a==--a) printf("true2\n"); a=10; if(a>--a) printf("true3\n"); else printf("false3\n"); return 0; }运行结果:
扩展:
c语言中运算符种类比较繁多,优先级有15种,结合性有两种。
如何记忆两种结合性和15种优先级?下面讲述一种记忆方法。
结合性有两种,一种是自左至右,另一种是自右至左,大部分运算符的结合性是自左至右,只有单目运算符、三目运算符的赋值运算符的结合性自右至左。
优先级有15种。记忆方法如下:
记住一个最高的:构造类型的元素或成员以及小括号。
记住一个最低的:逗号运算符。
剩余的是一、二、三、赋值。
意思是单目、双目、三目和赋值运算符。
在诸多运算符中,又分为:
算术、关系、逻辑。
两种位操作运算符中,移位运算符在算术运算符后边,逻辑位运算符在逻辑运算符的前面。再细分如下:
算术运算符分 *,/,%高于+,-。
关系运算符中,〉,〉=,<,<=高于==,!=。
逻辑运算符中,除了逻辑求反(!)是单目外,逻辑与(&&)高于逻辑或(||)。
逻辑位运算符中,除了逻辑按位求反(~)外,按位与(&)高于按位半加(^),高于按位或(|)。
这样就将15种优先级都记住了,再将记忆方法总结如下:去掉一个最高的,去掉一个最低的,剩下的是一、二、三、赋值。双目运算符中,顺序为算术、关系和逻辑,移位和逻辑位插入其中。
10.成员变量初始化的两种方法比较
a.通过在构造函数内赋值
class point { public: point(){ _x = 0; _y = 0;}; point( int x, int y ){ _x = 0; _y = 0; } private: int _x, _y; };b.使用初始化列表
class point { public: point():_x(0),_y(0){}; point( int x, int y ):_x(x),_y(y){} private: int _x, _y; };必须使用初始化列表的情况:1.const和引用数据成员被初始化时;2.需要初始化的数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化);
另外:随着类越来越大,越来越复杂,它们的构造函数也越来越大而复杂,那么对象创建的代价也越来越高,所以一般情况下建议使用初始化列表进行初始化,不但可以满足const和引用成员的初始化要求,还可以避免低效的初始化数据成员。
注:构造函数列表的初始化方式不是按照列表的的顺序,而是按照变量声明的顺序。
;>