实例介绍
该文档为自己通过网络搜集的关于c++笔试面试的基础资料,面向于应届、1-3年工作经验的c++开发者,希望大家能早日跳槽到好的单位。(另外还有一份资源是关于c++算法、编码和大量数据处理的资料,可以进我的频道里查找)
const int xa int const a: int const *k a const; 前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指 针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是·个指向整型数的常 指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味 着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指 针也是不可修改的)。如果应试者能止确回答这些问题,那么他就给我留卜了一个好印象 顺带提一句,也许你可能会问,即使不用关键宁 cons t,也还是能很容易写出功能正硝的 程序,那么我为什么还要如此看重关键字 cons t呢?我也如下的几下理由 关键字 cons t的作用是为给读你代码的人传达非常有用的信息,实际上,声明 个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下 的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用 const的程序员很少会留 下的垃圾让别人来清理的。) 2).通过给优化器一些附加的信息,使用关键字 const也许能产生更紧凑的代码。 3).合理地使用关键字 const可以使编译盎很自然地保护那些不希望被改变的参数,防止 其被无意的代码修改。简而言之,这样可以减少bug的出现。 、内存分配 1.内存的分配方式有几种? 从静态存储区域分配。内存在程序编译的时候就凵经分配好,这块内存在程序的整 个运行期间都存在。例如全局变量, static变量。 、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数 执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高, 但是分配的内存容量有限。 三、从堆上分配,亦称动态内存分。程序在运行的时候用 mallo或new中请任意多 少的内存,程序员自己负责在何时用frec或 delete释放内存。动态内存的生存期由我们决 定,使用非常灵活,但问题也最多。 2.堆和栈 从内存角度来说: 栈区( stack)由编译器自动分配释放,存放函数的参数值,局部变变量的值等,其操 作方式类似于数据结构中的栈,可静态亦可动态分配。 堆区(heap)一般由程序员分配释放,若程序员不释放,可能造成内存泄漏,程序结束 时可能由0S回收。只可动态分配,分配方式类似于链表 从数据结构角度来说:堆可以被看成是·棵树,如:堆排序。而栈是·种先进后出的数 据结构。 3.计算机加载程序包括哪几个区? 个由C/C+编译的程序占用的内存分为以下几个部分: (1)栈区( stack):一由编译器自动分配释放,存放函数的参数值,局部变量的值等。 可静态也可动态分配。其操作方式类似于数据结构中的栈 2)堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由Os 回收。动态分配。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表 3)仝局区(静态区):一程序结束后由系统释放,仝局变量和静态变量的存储是放在 块的,初始化的全局变量和静态变量在一块区域:未初始化的全局变量和静态变量在相邻 的另一块区域(BSS, Block Started by Symbo1),在程序执行之前BSS段会自动清0 4)文字常量区:一程序结束后由系统释放,常量字符串就是放在这里的 5)程序代码区:一存放函数体的二进制代码。 四、虚函数、多态、继承 1.虚函数实现机制,虚继承在 sizeof中有没有影响,构造函数能否为虚函数与纯虚函数 编译器公为每个有虚函数的类创建一个虚函数表,该虚函数表将被该类的所有对象共 享。类的每个虚函数占据虚函数表中的个指针。如果类中有N个虚函数,那么其虚函数衣 将有N4字节的大小。 编译器会自动的将类对象的前四个字节设置为虚函数表的地址。这意味着可以通过对象 实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数 没有虚函数和虚继承的类实例化后的对象大小至少为1字节(没有非静态数据成员的情 况下也要有1个字节米记录它的地址。 有纯虚函数的类为抽象类,不能定义抽象类的对象,它的子类要么实现它所有的纯虚函 数变为一个普通类,要么还是一个扣象类 特别的 1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回 类型不同,那么即使加上了 virtual关键字,也是不会进行滞后联编的。 2.只有类的成员函数才能说明为虚函数,因为虚函数仅适用于有继承关系的类对象,所 以普通函数不能说明为虚函数。 3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。 1.内联( inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚 区数在类的内部定义,但是在编译的时候系统仍然将它看做是非内联的。 5.构造凶数不能是虚函数,因为构造的时候,对象还是一片未定型的空问,只有构造完 成后,对象才是具体类的实例。 6.析构函数可以是虚函数,而且通常声明为虚函数,防止使用多态时没有析构了类,导 致内存泄漏。 2派生类虚表是什么样的? (1)单继承情况:先把基类的虚函数按顺序写到表里,然后子类中有覆盖基类的就替 换掉基类的虚函数,子类新实现的虚函数按声明顺序写到虚函数表后边。 (2)多重继承(无虚函数矍盖):按继承顺序写每个基类的虚函数表,子类的新虚函 数写到第一个虚函数表中 (3)多重继承(有虚函数覆盖):多重继承有多个虚函数衣,当了类对父类的虚函数 有重写时,子类的函数覆盖父类的函数在对应的虚函数位置,当子类有新的虚函数时,这些 虚函数被加在第一个虚函数表的后面 3.多态,虚函数,纯虚函数 多态:是对于不同对象接收相同消息时产生不同的动作。C+的多态性具体体现在运行 和编译两个方面:在程序运行时的多态性通过继承和虚函数来体现;在程序编译时多态性体 现在函数和运算符的重载上; 虚函数:在基类中冠以关键字 virtual的成员函数。它提供了一种接口。允许在 派生类中对基类的虚函数重新定义。 纯虚函数的作用:在基类中为其派生类保留一个函数的名字,以使派生类根据需要对它 进行定义。作为接口而存在纯虚函数不具备函数的功能,一般不能直接被调用 从基类继承来的纯虚函数,在派生类中仍是虚函数。如果个类中至少有个纯虚函数, 那么这个类被称为抽象类( abstract class) 抽象类中不仅包括纯虚函数,也可包括虚函数。抽象类必须用作派生其他类的基类,而 不能用」直接创建对象实例。但仍可使用指向抽象类的指针支持运行时多态性 4C+特点是什么?画出基类和子类在内存中的相互关系。 封装、继承和多态 子类继承父类大部分的资源,不能继承的有构造函数,析构函数,拷贝构造函数, operator 凶数,友元数等等 5“引用”与多态的关系? 引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的 派生类实例 6.多态的作用? 1)隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用; 2)接口重用:为了类在继承和派生的时侯,保让使用家族中任一类的实例的某一属性时的 正确调用 7类成员函数的重载、覆盖和隐藏区别? 答案 a成员函数被重载的特征: (1)相同的范围(在同一个类中) (2)函数名字相同; (3)参数不同,参数顺序不同也算不同 (4) virtual关键字可有可无。 (5)只是数返回值类型不同构不成重载,编译报错重定义。 b覆盖是指派生类函数覆盖基类函数,特征是 (1)不同的范围(分别位于派生类与基类); (2)函数名字和参数必须都相同 (3)基类函数必须有 virtual关键字。如果没有 virtual关键字基类被隐藏 C.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下: (1)如果派牛类的函数与基类的函数同名,但是参数不同。此时,不论有无 virtual关键字, 基类的函数将被隐藏(注意别与重载混淆)。 (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有ⅵ rtual关 键字。此时,基类的函数被隐藏(注意別与覆盖混淆) 8.派生类中构造函数与析构函数,调用顺序 构造函数的调用顺序总是如下 1).基类构造函数。如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现 的顺序,而不是它们在成员初始化表中的顺序 2).成员类对象构造函数。如果有多个成员类对象则构造函数的调用顺序是对象在类中 破声明的顺序,而不是它们出现在成员初始化表中的顺序。如果有的成员不是类对象,而是 基木类型,则初始化顺序按照声明的顺序来确定,而不是在初始化列表中的顺序 3).派生类构造函数 析构函数正好和构造函数相反。 9多态的例子 代码如下: #include iostream> using name space st class Vehicle public chicle(float speed, int total Vehicle: speed- speed Vehicle,: total total virtual void ShowMember(//虚函数 cout<<speed< protecte float speed nt total class Car: public Vehicle ublic Car(int aird, float speed, int total): Vehicle(speed, total) Car:: aird rd virtual void ShowMember(/虚函数 cout<<spced<<""<<total<<""<<aird<<endl int void test(vehicle &temp) temp. Show O int main o Vehicle a(120, 4) Carb(180,110,4) test(a) test(b) cin. get( test(a)调用 Vehicle类的成员函数;test(b)调用Car的成员函数。 五、指针、引用、数组、 1.什么是“引用”?声明和使用“引用”要注意哪些问题? 答:引用就是某个目标变量的“别名”,对引用的操作与对变量直接架作效果完全相同 声明一个引用的时候,一定要对其进行初始化,除非是做函数形参时。引用声明完毕后,相 当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名 的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别 名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。 不能建立数组的引用。 2.将“引用”作为函数参数有哪些特点? (1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来 主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是 对其相应的目标对象(在主调函数中)的操作。 (2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是苜接对实参操 作;而使用·般变量传递函数的参数,当发生函数调用吋,需要给形参分配存储单元,形参 变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的 数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。 (3)使用指针作为凶数的参数虽然也能达到与使用引用的效果,但是,在被调凼数中 同样要给形参分配存储单元,且需要重复使用”*指针变量名"的形式进行运算,这很容易 生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实 参。而引用更容易使用,更清晰。 因此,函数传参尽量用引用,因为指针还要提防为nu11。 3.在什么时候需要使用“常引用”? 如果既要利用引用提髙程序的效率,又要保护传递给函数的数据不在函数中被改变,就 应使用常引用。常引用声明方式: const类型标识符&引用名=目标变量名; 4.将“引用”作为函数返回值类型的格式、好处和需要遵守的规则? 格式 类型标识符&函数名(形参列表及类型说明) ∥/数体 好处:在内存中不产生被返回值的副木; 注意 (1)不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被 返回的引用就成为∫"无所指"的引用,程序会进入未知状态 (2)不能返回函数内部new分配的内存的引用。虽然不存在局部变量的被动销毁问题 可对」这种情况,又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出 现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释 放,造成内存泄漏。如 string aa= bb t fun(cc);假如其中的fun()函数就是返回 个new分配内存的话,在这里就造成∫内存泄漏。 (3)可以返回类成员的引用,但最好是 const。上要原因是当对象的属性是与某种业务 规则相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操 作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么 对该属性的单纯赋值就会破坏业务规则的完整性。 (4)流操作符重载返回值声明为“引用”的作用: 流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout<<"hclo"<<cnd;因此 这两个操作符的返回值应该是个仍然支持这两个操作符的流引用。可选的其它方案包括: 返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,稈序必须重新(拷贝) 构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法 让人接受。对丁返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是 惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C+ 语言中引入引用这亼概念的原因吧。赋值操作符=。这个操作符象沇操作符·样,是可以 连续使用的,例如:ⅹ=j=10;或者(x=10)-100;赋值操作符的返回值必须是一个左值,以便 可以被继续赋值。因此引用成了这个操作符的惟一返回值选择 例 f include <iostream.h> int&put(int n int vals[10]; int error=-l void maino put(O)=10;∥以put(0)函数值作为左值,等价于vals0=10; pu(9)=20;∥/以put(9函数值作为左值,等价于vals9}-20; cout<< vals[o] cout < vals Intceput(int n if(n>=0&&n<=9) return vals[n cout <<"subscript error return error. (5)在另外的一些換作符中,却千万不能返回引用:+*四则运算符。它们不能返回 引用。主要原因是这四个操作符没有 side effect,因此,它们必须构造一个对象作为返回 值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象 的引用、返回一个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3 两个方案都被否决了。静态对象的引用又因为((a+b)==(c+d)会永远为true而导致错误 所以可选的只剩下返回一个对象」 5.什么时候需要“引用”? 流操作符<和≯、赋值操作符-的返回值、拷贝构造函数的参数、赋值操作符-的参数 其它情况都推荐使用引用。 6常引用 例 int a const int&ra =a: ra=1;//错误,常引用不能二次赋值 =1;//正确 例2 string foo() void bar(string&s) 那么卜面的表达式将是非法的: bar(foo()) ar( hello 原因在于foo()和" hello world"串都会产生一个临时对象,而在C+中,这些临时对象都 是 const类型的。因此上面的表达式就是试图将一个 const类型的对象转换为非 const类型, 这是非法的。引用型参数应该在能被定义为 const的情况卜,尽量定义为cost。 7.指针和引用有什么分别;传引用比传指针安全,为什么?如果我使用常量指针难道不行 吗? (1)引用在创建的同时必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初 始化,可以在定义后面的任何地方重新赋值 (2)不存在NULL引用,引用必须与合法的存储单元关联;而指针则可以是NULL. (3)引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用;而指针在任 何时候都可以改变为指向另一个对象.给引用赋值并不是改变它和原始对象的绑定关系 (4)引用的创建和销毁并不会调用类的拷贝构造函数 (5)语言层面,引用的用法和对象·样;在二进制层面,引用般都是通过指针来实现的 只不过编译器帮我们完成了转换 不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引 用,显得很安全 const指针仍然存在空指针,并且有可能产生野指针 总的来说:引用既具有指针的效率,又具有变量使用的方便性和直观性 8 Iterator和指针的区别 游标是指针,但不仅仅是指针。游标和指针很像,功能很像指针,但是实际上,游标是 通过重载一儿的”米”和”->”来从容器中间接地返回一个值。 9指针的几种典型应用情况? int*pn];--指针数组,每个元素均为指向整型数据的指针。 int(*p)[n];—为指向·维数组的指针,这个维数组有n个整型数据。 t*O;—一函数带回指针,指针指向返回的值 int(*p)();-p为指向函数的指针 10.int(*s[10])(int)表示的是什么? int(*s[10])(int)函数指针数组,每个指针指向一个 int func( int param)的函 数。 11.下列声明分别表示什么意思? void*(*(*fp1)(int))[10]; float (*(*k fp2)(int, int, int))(int) int((来fp3)()[10]0 1.void *(*(*fp1)(int))[i fpl是一个指针,指向一个函数,这个函数的 参数为int型,函数的返回值是个指针,这个指针指向个数组,这个数组有10个元素, 每个元素是一个void*型指针。 2.f1oat(*(*fp2)(int,int,int)(int);fp2是一个指针,指向一个函数,这个 凶数的参数为3个int型,函数的返回值是一个指针,这个指针指向一个函数,这个函数的 参数为int型,函数的返回值是 float型。 3.int(*(*3)0[10]0;fp3是个指针,指向个函数,这个函数的参数 为空,函数的返回值是一个指针,这个指针指向一个数组,这个数组有10个元素,每个元 素是一个指针,指向一个函数,这个函数的参数为空,函数的返回值是int垩。 六、结构、联合、类 1.结构与联合有和区别? 结构的各数据成员分别占用独立的内存空间,修改其中一个成员不影响其他:而联合中所 有的成员公用同一块内存空间,修改一个成员影响其他 2.下面关于“联合”的题目的输出? 例 t include <stdio.h> union nt 1; char x[21 【实例截图】
【核心代码】
标签:
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论