《近期出现的C++面试题整理(附详细答案).docx》由会员分享,可在线阅读,更多相关《近期出现的C++面试题整理(附详细答案).docx(58页珍藏版)》请在课桌文档上搜索。
1、第一部分:简答题1.一下C+中SUUijCaSt和dynamic_casi的区别。答:NatijCa“用有比较明确定义的变换,包括不需要强制转换的变换。dynamiJCaSt适用于类型安全的向下转换,常用在继承中的父类指针向子类指针的转换.若转换成功则返网改类型的指针,若失败,则返【可NU1.1.1. Struct和ClaSS的区别。答:struct是一种结构体类型的标志,它和C+中的Class很相似。C+中两者的唯一区别在于:ClaSS定义中默认情况卜的成员都是私有的,而结构StrUCl定义中默认情况下的成员都是公有的,在C中,结构中不能有成员函数,而在C+中可以有成员函数.1 .是不是一个
2、父类写了一个VirtUal函数,如果子类覆蛊它的函数不加Virtua1,也能实现多态?答:VirtUal修饰符会被隐形继承的。PriValC也被继承,只是派生类没有访问权限而已。VimIal可加可不加。子类的空间里有父类的所有变量(StatiC除外)。同一个函数只存在个实体(Hine除外)。子类覆盖它的函数不加VirtUaI.也能实现多态。在子类的空间里,有父类的私有变量.私有变盘不能直接访问.1.C和C+有什么不同?(从机制,适用象域等方面说说)答:从机制上:C是面向过程的(但C也可以编写面向对象的程序:C+是面向对象的,提供了类。但是,C+编写面向对象的程序比C容易从适用的方向:C适合要求
3、代码体枳小的,效率高的场合,如嵌入式:C+适合更上层的,发杂的:HinUX核心大部分是C写的,因为它是系统软件,效率要求极高。从名称上也可以看出,C+比C多了+,说明C+是C的超桀:那为什么不叫C+而叫C+呢,是因为C+比C来说扩充的东西太多了,所以就在C后面放上两个+;于是就成了C+C语言是结构化编程语言,C+是面向对象编程语言。C+,侧或于对象而不是过程,倜应于类的设许而不是逻辑的设计。1 .请说出COnsl与#define相比,有何优点?答:1) COnSt常量有数据类型,而宏常量没有数据类型。编译罂可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能
4、会产生意料不到的错误。2)有些集成化的调试工具可以对const常量进行调试,但是不能时宏常量进行调试。1 .简述数组与指针的区别?答:数组要么在静态存储区被创建(如全局数组),要么在枝上被创建。指针可以随时指向任意类型的内存块.(1)修改内容上的差别chara=hello;a0=*X,;char*p=world”;注意P指向常量字符串p0=X;/编译器不能发现该错误,运行时错误(2)用运律符Seof可以计算出数组的容兄(字节数)sizeof(p),p为指针得到的是一个指针变量的字节数,而不是p所指的内存容量。C+/C语言没有办法知道指针所指的内存容量,除非在申谙内存时记住它。注意当数组作为函数
5、的参数进行传递时,该数组自动退化为同类型的指针。chara=,helloworld;char*p=a;coutsize(八)endl;/12字节coutSiZeor(P)endl;/4字节计算数组和指针的内存容垃voidEunc(chara100)coutsizeof(八)endl;/4字节而不是100字节)1 .类成员函数的重载、覆盖和隐藏区别?答:a成员函数被全载的特征:(I)相同的范围(在同一个类中):(2)函数名字相同;(3)参数不同:(4) VirtUal关键字可有可无。b.覆盖是指派生类函数覆盖基类函数,特征是:(1)不同的范圉(分别位于派生类与基类);(2)函数幺字相同:参数相同
6、:(4)基类函数必须有VirtUaI关键字。c“隐成”是指派生类的函数屏蔽了与其同名的基类函数,规则如F:(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被阮版(注意别与重载混消)。(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有VirtUal关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)1 .面向对象的三个基本特征,并简堆叙述之?1 .封装:将客观事物抽象成类,每个类对自身的数据和方法实行protcction(privatc.protcctcd.public)2 .维承:广义的继承有三种实现形式:实现继承(指使
7、用堪类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对以组合=接口继承以及纯虚函数)构成了功能曳用的两种方式.3 .多态:是将父对象设置成为和个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作.简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。9.请简单描述Windows内存管理的方法.答:内存管理是操作系统中的重要部分,两三句话恐怕谁也说不清她吧我先说个大概,希望能够抛砖引玉吧当程序运行时需要从内存中读出这段程序的代码
8、。代码的位置必须在物理内存中才能被运行,由于现在的操作系统中有非常多的程序运行着,内存中不能够完全放下,所以引出了虚拟内存的概念。把哪些不常用的程序片断就放入虚拟内存,当需要用到它的时候在Ioad入主存(物理内存)中。这个就是内存管理所要做的事。内存管理还有另外一件事需要做:计算程序片段在主存中的物理位置,以便CPU调度。内存管理有块式管理,页式管理,段式和段页式管理。现在常用段页式管理块式管理:把主存分为一大块、一大块的,当所需的程序片断不在主存时就分配一块主存空间,把程序片断load入主存,就算所需的程序片度只有几个字节也只能把这块分配给它。这样会造成很大的浪费,平均浪费了50%的内存空间
9、,但时易于管理.页式管理:把主存分为页页的,每一页的空间要比一块块的空间小很多,显然这种方法的空间利用率要比块式管理裔很多。段式管理:把主存分为一段一段的,每一段的空间又要比一页一页的空间小很多,这种方法在空间利用率上又比页式管理面很多,但是也有另外一个缺点。一个程序片断可能会被分为几十段,这样很多时间就会被浪费在计算每一段的物理地址上(计算机最耗时间的大家都知道是吧)。段页式管理:结合了段式管理和页式管理的优点。把主存分为若干页,每一页又分为若干段。好处就很明显,不用我多说了吧。各种内存管理都有它自己的方法来计算出程序片断在生存中的物理地址,其实都很相似。这只是一个大概而已,不足以说明内存管
10、理的皮毛。无论哪一木操作系统书上都有详细的讲解10. main主函数执行完毕后,是否可能会再执行一段代码,给出说明?答:可以,可以用ncxit注册一个函数,它会在main之后执行intfnl(void).fn2(void).fn3(void).fn4(void):voidmain(void)(Stringstr(zhanglin):_onexit(fnl):_onexit(fn2);_OneXit(fn3);_onexit(fn4);printf(*4Thisisexecutedfirst.n);)intfnl()(printf(next.n):return0;)intfn2()print(e
11、xecuted);return0:)intfn3()(prinl(is);return0;)intfn4()(printf(This);returnO:)Csdn文档摘要:The_onexitfunctionispassedtheaddressofafunction(func)tobecalledwhentheprogramt。HninatoSnormally.SuccessivecallstoOneXilcreatearegisteroffunctionsthatareexecutedin1.IFO(last-in-first-out)order.Thefunctionspassedtoon
12、exitcannottakeparameters.11. const符号常量:(1)constchar*p(2)charconst*p(3)charconstp说明上面三种描述的区别.答:如果COnSt位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果COnSl位于星号的右侧,con“就是修饰指针本身,即指针本身是常量“(l)constchar*p个指向Char类型的ConSt对象指针,P不是常量,我们可以修改P的值,使其指向不同的Char.但是不能改变它指向非Char时象,如:constchar*p:charcl=a,;charc2=b,:p=Acl;/okP=
13、AC2;Ok*p=cl;/error(3)char*constp此时*p可以修改,而P不能修改。(4)constchar*constp这种是地址及指向对象都不能修改。12 .下面是C语言中两种if语句判断方式.请问哪种写法更好?为什么?答:intn;if(11=10)/第一种判断方式if(10n)/第二种判断方式如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了=13 .*P+自增P还是P所指向的变量?答:后缀”和操作符本版上比前缀书操作的优先级高,因此%+和+)等价,它自增p并返回p自增之前所指向的值.要自增P指向的值.使用(*p)+.如果副作用的顺序无关索要也可以使用+
14、冲。14 .Upragma是什么.有什么用?答:即ragam指令提供了一种单一的明确定义的“救生舱”,可以用作各种(不可移植的)实现相关的控制和扩展:源码表控制、结构压缩、警告去除(就像IinI的老*Notreached*择).等等。15 .+pragmaonce”是什么意思?我在一些头文件中看到了它。答:这是某些预处理器实现的扩展用于使头文件自我识别;它跟#ifndef技巧等价.不过移植性差些.16 .进程间通信的方式有?答:进程间通信的方式有共享内存,管道,Socket,消息队列,DDE等17 .如何打印出当前源文件的文件名以及源文件的当前行号?COUt_FI1.E_;cout_1.INE
15、_;一FI1.E_和_1.1NE_是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的”18 .如何判断段程序是由C编译程序还是由C1编洋程序编洋的?答:#ifdcf_cplspluscout,c+f,:UelseCOUta/=(k+m)*l*(k+m):=a=a/9:=a=1:2.下面的代码有什么问题?voidDoSomeThing()char*p;P=malIoc(1024):/分配IK的空间if(NU1.1.=p)return;*P=realIoc(p,2048):/空间不够,重新分配到2Kif(NU1.1.=p)return;)答:P=malIoc(1024):应该写成:
16、p=(char*)malloc(1024);没有释放P的空间,造成内存泄漏.3 .写出运行结果:/testlcharstr=mworld;CoUlSiZeof(Slr),“.(char*p=str:coulSiZeof(P)charicutsizeof(i)void*ppInalloc(IO);cutSiZeor(P)endl;)答:6:4:I:44 .下面的代码有什么问题?并请给出正确的写法。voidDoSomeThing(char*p)(charstr16;intn;assert(NU1.1.!=p):sscanf(p,4,%s%d,str,n);if(Ostrcmp(str,someth
17、ing)()答:sscanf(p,44%s%d,str,n):这句该写成:sscanf(p.,%s%d,str.&n):5 .inti=10,j=10,k=3:k*=i+j;k最后的值是?答:606.structchart:4;chark:4:unsignedshorti:8;unsignedlongm;)Sizeof(八)=?(不考虑边界对齐)答:7structCE1.1./DeclareCE1.1.bitfieldunsignedcharacter:8:/00000000?unsignedforeground:3;/OooO0?00000000unsignedintensity:1:/()
18、000?00000000000unsignedbackground:3:/0?000000000000unsignedblink:i:/7000000000000000)screen2580;/Arrayofbitfields二、位结构位结构是一种特殊的结构,在需按位访问一个字节或字的多个位时,位结构比按位运算符更加方便.位结构定义的一般形式为:struct位结构名数据类型变批名:整型常数;数据类型变量名:整型常数;位结构变量;其中:数据类型必须是int(unsigned或signed)。整型常数必须是非负的整数,范围是015,表示二进制位的个数,即表示有多少位。变星名是选择项,可以不命名,这
19、样规定是为了排列需要。例如:卜.面定义了一个位结构。structunsignedincon:8;*incon占用低字节的07共8位*/unsignedIxcolor:4;/*IXColor占用高字节的03位共4位*/unsignedbgcolor:3;/*bgcolor占用高字节的46位共3位*/unsignedblink:1:*blink占用高字节的第7位*/ch;位结构成员的访问与结构成员的访问相同.例如:访问上例位结构中的bgcolor成分可写成:ch.bgcolor注意:1 .位结构中的成员可以定义为UnSign也可定义为Signal,但当成员度为1时,会被认为是UnSignCd类型。
20、因为单个位不可能具有符号。2 .位结构中的成员不能使用数组和指针,但位结构变量可以是数组和指针.如果是指针.其成员访问方式同结构指针。3 .位结构总长度(位数).是各个位成员定义的位数之和,可以超过两个字节。4 .位结构成员可以与其它结构成员一起使用。例如:structinfocharname8:intage;structaddraddress:floatpay:unsignedstate:1:unsignedpay:1;)workers;上例的结构定义了关于一个工人的信息。其中有两个位结构成员,每个位结构成员只有一位,因此只占一个字节但保存了两个信息.该字节中第一位表示工人的状态,第二位表示
21、工资是否已发放。由此可见使用位结构可以节.省存贮空间。7 .卜面代码有什么问题?Voidtest3(char*slrl)charstring10;if(slrlen(strl)j+)三(i+=j)i+=j;答:i=510.输出卜面程序结果。JiincludeclassA(public:virtualvoidprint(void)(cout,*A:print0,endl;):classBrpublicA(public:virtualvoidprint(void)Icoutr,B:print()endl;):):classCzpublicBpublic:virtualvoidprint(void)
22、(coutwC:print()”print():pc-printO;print(八);print(b);print(c);)答::print()B:print()C:print()AiprintOB: :print()C: :print():print()A:print()A:print()11.uniona(intainll;doublea_double;intaint2;):chary;)b:classc(doublecdouble;bbl;aa2:):输1.hCOUtvVSiZeOf(C)VVendl:的结果?答:VC6环境卜.得出的结果是32另:我(NUn)在VC6.0+win2k下做
23、过试验:short-2int-4float-4double-8指针-4sizeof(union),以结构里面Size最大的为union的size对于字节对齐的问题,有儿点需要注意理解:(I)字节对齐是语言实现相关(编译落),而非C+特性(2)对于cl.cxc编译器:A.为r编译器寻址方便快捷,默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(ShOn等)都位于能被2整除的地址上,让宽度为4的基本数据类型(im等)都位于能被4整除的地址上,以此类推。B,还要注意的是,编译器会让结构体的大小是【最大成员】的整数倍。基于上述原则我们就可以算出结构体的内存大小,当然
24、这也是SiZCof的实现原理。编译器看到的掂本类型,而非使用了SizCOf取大小的复合类型,再用这个例子解糅一遍:最大成员是double8字节,而非StrUClb16字节,则整个SlrUCl的大小能被8整除】classc(doublec_double;/偏移0bbl:/bl.al偏移8(SiZeOf(JdOUbIe)/bl.y偏移8(sizeof(bl.al)aa2;/【注意:】由于a2为double,需要放在为8倍数的偏移地址上(原则2.a)偏移8,而非SiZeof(bl.y)/a2占有8个字节,到此整个C的内存空间为32,也刚好为最大成员占有内存8的整数倍,不需要在尾部补齐字节):所以:s
25、izeof(c)32如果我们再往后面添加两个成员,如下:classc(doublec_double;/偏移0bbl:/同上aa2;/同上intx;/偏移8(SiZCOf(a2)【到此地址已经为C分配了32字节了】shortk;/偏移4(SiZCof(X)【到此C有36字节】/k占有2个字节,为38,但由于不能被最大成员8整除,所以在编译港在尾部补上两个字节【原则2力】);则sizeof(c)=40有个测试代码:uniona(inta_intl;doublea_double;inta_int2:):typelefstructchary;)b;classc(public:doublecdouble
26、;bbl;aa2:shortx;intk;):includeusingnamespacestl:voidmain()void*p=&(test.bl.y);coulendl;“Addressoftest,cdouble:&(IeSI.clouble)fc(tesl.bl.al)endlpendl;coulAddressoftest.bl.al:coutAddressoftest.bl.y:COUlmAddressoftest.a2:&(IeSja2)endl;COUl“Addressoftest,x:”ft(lest.x)endl;COUtwAdrrossoftest,k:”&(test,k)
27、endl;COUt)uSizeofclass;c:sizeof(test)endl:12.41.分析一下这段程序的输出(Auiodcsk)classB(public:BOCoUldefaulconstructorendl;)、B0(coutdestructedinstanceofB)cout*constructedbyParamelerdataendl;private:intdata;);BPlay(Bb)(returnb:)答:(1)results:intmain(intargc,char*argv)constructedbyparameter5(destructedB(5)形参析构构造函数
28、可以做默认的类型转换Btl=Play(5);Bt2=Play(tD;destructedtl形参析构return0;destructedt2注意顺序!tl和t2是在程序的栈区存放的,先进后出)destructedtl(2)results:intmain(intargc,char*argv)constructedbyparameter5destructedB(5)形参析构BIl=Play(5);B12=Play(10):constructedbyparameterIOreturn0;destructedB(IO)形参析构)destructedt2注意顺序!destructedtl13.写出程序结
29、果:voidFunc(charstr100)(printf(%dnw,sizeof(str):)答:4.指针长度14,求下面函数的返回值intfunc(x)(intCountx=0:WhiIe(X)COUDtX+:x=xft(x-l);)returncountx:)答:X中I的个数。PS:这里说点闲话,前两天我参加华硕的笔试,最后一道题就是这个题,可是他是叫我写出这个程序,可我只记得使用位运算做的,具体有点遗忘了,后来没写出来,这个对我触动很深,感觉自己学的还是流于表面,没有抓到精愉。希望大家不要像我样,学东西还是要学的透彻,不然就容易错失机会。15,程序改错classnml(private:
30、staticunsignedintx:public:raniO(x+;11ml(staticunsignedintft)(x+:)mini(x-;)pulic:virtualmon()=0:staticunsignedintnunc()returnx;);classnnl:public11unl(private:staticunsignedinty;public:nnlO(x+;nnl(staticunsignedint&)x+;)nnlx-public:virtualmonOU;staticunsignedintnnc()returny;):代码片断:mml*pp=newnnl;delete
31、pp;1-W基类的析构函数应该为虚函数virtualmmlx-:16,请指出下列程序中的错误并且修改voidGetMemory(char*p)(P=(char*)mdIoc(100):)voidTest(void)char*str=NU1.1.;GetMemory(Str);strcpy(str,whelloworld);prinlf(slr);)答:错误参数的值改变后,不会传回GetMemory并不能传递动态内存,Test函数中的Str宜都是NU1.1.。strcpy(str,helloWolid”);将使程序崩渍。修改如F:char*GeIMemoryOchar*p-(char*)mall
32、oc(100):returnp:)voidTest(void)char*str=NU1.1.:Slr=GetMemoryO;strcpy(str,hoiIoworld);printf(str);)方法二:VOidGetMemory2(Char*)变为二级指针.*p=(Char*)ma1Ioc(sizeOf(Char)*num);)17.下面关于“联合”的胭目的输出?a)#includeunion(inti;charx2;)a;voidmain()(a.x0=10:a) xl=1;printf(44%d,a.i);)答案:266(低位低地址,高位离地址,内存占用情况是ONoIOA)b) main
33、()union(*定义一个联合*/inti:struct/*在联合中定义一个结构*/charfirst;charsecond;)half;)number:number,i=04241;*联合成员赋值*/printf(4,%c%cn,number,half,first,number.half,second):number,half,first=*a,;*联合中结构成员赋值*/number,half,second=*b;printf(4,%xn,number,i):getch():)答案:AB(041对应,A是低位:0x42对应,B二是高位)6261(number,i和nunber.half共用一
34、块地址空间)第三部分:编程题1.已知类String的原里为:classString(public:String(constchar*str=NU1.1.);/普通构造函数String(constStringAothcr):/拷贝构造函数Slring(void);/析构函数String&operate=(constStringfiother);/赋值函数private:char*m.data:/用于保存字符串):谙编写Slring的上述4个函数。答:构造函数String:String(constchar*str)(首先判断传过的字符串是不是空字符串if(str=NU1.1.)(indata=ne
35、wcharl;如果是NU1.1.,直接开辟空间后内容清零indata=t0,;)else(intlength=strlcn(str):m_data=newcharlength+1;/对于new出的空间不用判断是否并辟成功,因为在编译过程中有IhrOw()CatCho机制strcpy(m_data,str);析构函数String:String(void)Ideletem_data;这里一定要加否则删除不干净)密贝构造函数String:String(constStringAother)(intlength=strlen(other.m_data);m_data=newcharlength+1;Sl
36、rcpy(indata,other,indata);)赋值重载函数String&String:operate=(constStringother)(首先检查自赋值if(this!=fiothor)(分配新的内存空间,并拷贝内容char*tcmp=newcharstrlen(other.m_data)+1;Slrcpy(temp,other,11data);记住一定要释放原有的资源delete11m_data;strcpy(m_data,temp):)return*this;)2.已知strcpy函数的原型是:char*strcpy(char*strDest,constchar*strSrc);
37、其中StrDCSt是目的字符串,sirSrc是源字符串。不调用C+/C的字符串库函数,请编写函数strcpy答:因为这道题用到const,所以用的是C+既然是用C,那么我们可以用异常,代码如下Char*nystrcpy(Char*StrDcst,constchar*strSrc)if(StrDest=MJ1.1.11StrSrc=NU1.1.)(throwruntime_error(44StrDest=NU1.1.IStrSrc=NU1.1.);char*temp=StrDest:whiIe(*StrDest+=*strSrc+)!=0);/emptyreturntemp;)但是C+语法中有一
38、个漏洞,那就是支持constCha产到Char*的转换(还是默认的),所以如下代码,在编译期可以通过niysticpy(,HelloAvorld,hello,world);很明显,这是不允许的,C+中我们需要防止这一类事情发生所以我们可以参照类中禁止史制和赋值的方法,声明但不实现这个函数char*mystrcpy(constchar*,constchar*);这样子,在健接期,编译器会抛出一个链接错误,我们就可以修正,所以,这道题的完整答案,如下char*mystrcpy(char*StrDest,constchar*strSrc)i(SlrDesl=NU1.1.11SIrSrC=NU1.1.)(throwruntime.error(StrDest=NU1.1.IStrSrc=NU1.1.w);char*temp=StrDest:whiIe(*StrDest+=*strSrc+)!=0);/emptyreturntemp;)char*mystrcpy(constchar*,constchar*);声明但不定义1.输入一个