程序员面试题整理(非算法题)
- 格式:doc
- 大小:1.07 MB
- 文档页数:60
程序员面试题集锦导言程序员面试是找工作过程中至关重要的一步,它不仅检验了应聘者的技术能力,还考察了他们的解决问题和沟通能力。
本文档是一个面试题集锦,旨在帮助程序员准备各种常见的面试题,并提供详细的答案和解析。
目录1.数据结构与算法2.操作系统3.数据库4.编程语言5.网络与安全数据结构与算法1. 什么是数组?如何在数组中查找一个元素?•数组是一种线性数据结构,用于按顺序存储相同类型的元素。
•要在数组中查找一个元素,可以使用线性搜索(遍历每个元素直到找到目标元素)或二分查找(适用于已排序数组)。
2. 什么是链表?请介绍链表的几种类型。
•链表也是一种线性数据结构,但不像数组需要连续内存空间。
•链表有多种类型,包括单向链表、双向链表和循环链表等。
3. 什么是栈和队列?它们有何区别?•栈和队列都是用于存储和访问数据的特定数据结构。
•栈是一种后进先出(LIFO)的数据结构,只能在栈顶插入或删除元素。
•队列是一种先进先出(FIFO)的数据结构,可以在队尾插入元素,在队头删除元素。
4. 请解释以下排序算法:冒泡排序、插入排序、选择排序、快速排序、归并排序。
•冒泡排序:通过比较相邻元素交换位置,每次循环将最大元素移到末尾。
•插入排序:将数组分为已排序和未排序两部分,逐个将未排序元素插入已排序部分的合适位置。
•选择排序:在数组中选择最小元素放到已排序部分的末尾,依次重复这个过程直到整个数组有序。
•快速排序:通过选取一个基准值将数组划分为两个子数组,小于基准值的在左侧,大于基准值的在右侧。
然后对左右子数组递归地进行快速排序。
•归并排序:将数组切分成更小的子数组,对子数组进行递归地归并排序后再合并。
操作系统1. 什么是进程和线程?它们有何区别?•进程是程序在操作系统中的一个执行实例,拥有独立的内存空间和资源。
•线程是进程中的一个执行单元,多个线程可以共享相同的内存和资源。
•主要区别在于进程之间的切换开销较大,而线程之间的切换开销较小。
程序员面试题库及答案在程序员求职的过程中,面试是一个非常重要的环节。
而为了更好地准备面试,掌握程序员面试题库及答案是至关重要的。
下面将为你提供一份程序员面试题库及答案,帮助你在面试中更好地展现自己的技能和知识。
一、数据结构与算法1. 什么是栈?请写出栈的基本操作。
答案:栈是一种具有后进先出(Last In First Out,简称LIFO)特点的数据结构。
栈的基本操作包括入栈(push)、出栈(pop)、获取栈顶元素(top)以及判断栈是否为空(isEmpty)。
2. 什么是队列?请写出队列的基本操作。
答案:队列是一种具有先进先出(First In First Out,简称FIFO)特点的数据结构。
队列的基本操作包括入队(enqueue)、出队(dequeue)、获取队头元素(front)以及判断队列是否为空(isEmpty)。
二、编程语言1. 请简要介绍一下面向对象编程(Object-Oriented Programming, OOP)的概念及特点。
答案:面向对象编程是一种编程范式,它的核心思想是将现实世界的事物抽象成对象,并通过对象之间的交互来完成任务。
面向对象编程的特点包括封装、继承和多态。
2. 请列举几个面向对象编程中常用的设计模式,并简要说明其应用场景。
答案:常用的面向对象编程设计模式包括工厂模式、单例模式和观察者模式。
- 工厂模式用于创建对象,通过工厂类的统一接口来实现对象的创建和初始化。
- 单例模式用于限制某个类只能存在一个实例,常用于全局资源共享或者对象唯一性的场景。
- 观察者模式用于实现对象之间的一对多依赖关系,当一个对象发生改变时,所有依赖它的对象都会得到通知。
三、数据库1. 什么是关系型数据库(Relational Database)?答案:关系型数据库是一种以表格的形式组织数据的数据库系统,通过表之间的关系来建立数据之间的联系。
关系型数据库使用结构化查询语言(Structured Query Language, SQL)进行数据的操作和查询。
程序员八股文面试题
程序员八股文面试题通常是一些关于编程语言、算法和数据结构的经典问题,这些问题在不同的公司和面试中都可能被使用。
以下是一些常见的程序员八股文面试题:
1. 请你解释一下什么是冒泡排序,并给出一个示例代码。
2. 请你解释一下什么是二叉树,以及二叉树有哪些遍历方式。
3. 请你解释一下什么是栈,以及栈有哪些操作。
4. 请你解释一下什么是队列,以及队列有哪些操作。
5. 请你解释一下什么是链表,以及链表有哪些特点。
6. 请你解释一下什么是哈希表,以及哈希表有哪些应用场景。
7. 请你解释一下什么是递归,以及递归有哪些应用场景。
8. 请你解释一下什么是动态规划,以及动态规划有哪些应用场
景。
9. 请你解释一下什么是多线程,以及多线程有哪些应用场景。
10. 请你解释一下什么是异常处理,以及异常处理有哪些常见的错误类型。
这些问题都是为了测试程序员的基础知识和技能水平。
在回答这些问题时,建议先理解问题的背景和含义,然后给出清晰的答案,并尽量用简单的语言解释概念和代码实现。
同时,也需要对面试官的问题进行适当的扩展和讨论,以展示自己的专业能力和思维能力。
c++程序员面试题目
以下是一些可能的C++程序员面试题目:
1. 基础知识:请解释C++中的指针和引用有什么区别?什么是STL?什么是异常处理?
2. 编程技能:请写一个C++程序,实现一个简单的计算器,可以进行加、减、乘、除运算。
请描述一下您在编程中常用的数据结构和算法有哪些?
3. 系统设计:请描述一下您在项目开发中如何进行模块划分和接口设计?如何进行性能优化?
4. 数据库操作:请写一个C++程序,实现从数据库中读取数据并输出到控制台。
您使用过哪些数据库?如何进行数据库连接和操作?
5. 网络编程:请写一个C++程序,实现基于TCP协议的网络通信。
您了解哪些网络编程模型?如何处理并发连接?
6. 系统架构:请描述一下您对分布式系统的理解。
您如何解决系统中的一致性和同步问题?
7. 算法和数据结构:请写一个C++程序,实现一个二叉搜索树。
您能给出一些常用的排序算法吗?
8. 项目经验:请介绍一下您参与过的最有成就感的一个项目。
在这个项目中,您负责哪些工作?您遇到了哪些挑战,又是如何解决的?
9. 团队协作:请描述一下您在团队中是如何协作的。
您如何处理与其他成员的冲突?
10. 学习能力:请谈谈您最近学习的一项新技术或新知识。
您是如何学习的?学习过程中遇到了哪些困难,又是如何克服的?。
程序员面试题精选100题完整版很全面,很经典的程序员面试题精选100题,包括网络编程,socket编程,c++/c编程程序员面试题,linux/windows网络编程面试必备。
程序员面试题精选100题前言随着高校的持续扩张,每年应届毕业生的数目都在不断增长,伴随而来的是应届毕业生的就业压力也越来越大。
在这样的背景下,就业变成一个买方市场的趋势越来越明显。
为了找到一个满意的工作,绝大多数应届毕业生都必须反复经历简历筛选、电话面试、笔试、面试等环节。
在这些环节中,面试无疑起到最为重要的作用,因为通过面试公司能够最直观的了解学生的能力。
为了有效地准备面试,面经这个新兴概念应运而生。
笔者在当初找工作阶段也从面经中获益匪浅并最终找到满意的工作。
为了方便后来者,笔者花费大量时间收集并整理散落在茫茫网络中的面经。
不同行业的面经全然不同,笔者从自身专业出发,着重关注程序员面试的面经,并从精选出假设干具有代表性的技术类的面试题展开讨论,希望能给读者带来一些启发。
由于笔者水平有限,给各面试题提供的思路和代码难免会有错误,还请读者批评指正。
另外,热忱欢送读者能够提供更多、更好的面试题,本人将感谢不尽。
(01)把二元查找树转变成排序的双向链表题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创立任何新的结点,只调整指针的指向。
比方将二元查找树10/ \6 14/ \ / \4 8 12 16转换成双向链表4=6=8=10=12=14=16。
分析:此题是微软的面试题。
很多与树相关的题目都是用递归的思路来解决,此题也不例外。
下面我们用两种不同的递归思路来分析。
思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。
最近链接左子链表的最右结点〔左子树的最大结点〕、当前结点和右子链表的最左结点〔右子树的最小结点〕。
从树的根结点开始递归调整所有结点。
程序员面试题精选100题1. 什么是面向对象编程(OOP)?列举几种常见的面向对象编程语言。
2. 解释一下封装、继承和多态的概念。
3. 什么是数据结构?列举几种常见的数据结构。
4. 解释一下栈和队列的概念,并提供它们的实际应用场景。
5. 什么是算法?解释一下时间复杂度和空间复杂度的概念。
6. 解释一下HTTP协议的工作原理。
7. 什么是数据库事务?解释一下ACID原则。
8. 解释一下前端开发中的MVC和MVVM模式。
9. 解释一下正向代理和反向代理的区别。
10. 什么是RESTful API?列举一些常见的HTTP请求方法。
11. 解释一下同步和异步的概念,以及它们的区别。
12. 解释一下进程和线程的概念,并提供它们的区别。
13. 解释一下操作系统中的死锁问题,以及如何避免死锁。
14. 解释一下TCP/IP协议族的组成部分。
15. 什么是单元测试?解释一下TDD(测试驱动开发)的概念。
16. 解释一下版本控制系统中的分布式版本控制和集中式版本控制的区别。
17. 什么是软件设计模式?列举几种常见的软件设计模式。
18. 解释一下Web应用程序中的会话管理机制,以及如何处理会话跟踪。
19. 解释一下缓存的工作原理,并提供一些常见的缓存算法。
20. 什么是虚拟机?解释一下虚拟化技术的概念。
21. 解释一下操作系统中的文件系统,以及不同类型的文件系统。
22. 解释一下数据库索引的概念,以及为什么使用索引可以提高查询性能。
23. 什么是反射?解释一下反射在Java中的应用。
24. 解释一下关系型数据库和非关系型数据库的区别。
25. 什么是分布式系统?列举一些常见的分布式系统架构。
26. 解释一下HTTP和HTTPS的区别,以及为什么使用HTTPS更安全。
27. 解释一下云计算的概念,以及云计算的优势和劣势。
28. 什么是容器化?解释一下Docker的工作原理。
29. 解释一下RESTful风格的API设计原则。
程序员面试逻辑题集合趣味智力题尽管把这种题目归为一个大类,但他们本身之间却绝少一样的地方。
每一个题目都需要你打破思维的常规来回答。
稍有不慎,就可能落入骗局。
例题1:你让工人为你工作7天,给工人的回报是一根金条。
金条平分成相连的7段,你必需在天天完毕时给他们一段金条,若是只许你两次把金条弄断,你如何给你的工人付费?小蒲〔此刻微创工作,去年遭遇这道试题〕:这道试题相对其它一些微创考题仍是简单的,可仍然把我弄得头大。
那时我是如此做这道题的。
两次弄断就应分成三份,我把金条分成1/7、2/7和4/7三份。
如此,第1天我就能够够给他1/7;第2天我给他2/7,让他找回我1/7;第3天我就再给他1/7,加上原先的2/7确实是3/7;第4天我给他那块4/7,让他找回那两块1/7和2/7的金条;第5天,再给他1/7;第6天和第2天一样;第7天给他找回的那个1/7。
整理搜集:倩倩靜聽例题2:此刻小明一家过一座桥,过桥时候是黑夜,因此必需有灯。
此刻小明过桥要1秒,小明的弟弟要3秒,小明的爸爸要6秒,小明的妈妈要8秒,小明的爷爷要12秒。
每次此桥最多可过两人,而过桥的速度依过桥最慢者而定,而且灯在点燃后30秒就会熄灭。
问小明一家如何过桥?参考答案:这种智力题目,实际上是考察应聘者在限制条件下解决问题的能力。
具体到这道题目来讲,很多人往往以为应该由小明持灯来来去去,如此最节省时刻,但最后却怎么也凑不出解决方案。
可是换个思路,咱们依照具体情形来决定谁持灯来去,只要稍稍做些变更即可:第一步,小明与弟弟过桥,小明回来,耗时4秒;第二步,小明与爸爸过河,弟弟回来,耗时9秒;第三步,妈妈与爷爷过河,小明回来,耗时13秒;最后,小明与弟弟过河,耗时4秒,总共耗时30秒,何等惊险!专家意见:这种题目多显现于跨国企业的招聘面试中,对考察一个人的思维方式及思维方式转变能力有极为明显的作用,而据一些研究显示,如此的能力往往也与工作中的应变与创新状态息息相关。
高级程序员面试题及答案1.请介绍你在项目中所负责的任务和职责。
答案:在项目中,我主要负责需求分析、设计、编码和测试等工作。
我通过与产品经理和客户沟通,理解需求,并确定技术实现方案,进行系统设计和架构。
同时,我也会与开发团队协作,编写高质量的代码,保证项目进度和质量。
此外,我也负责测试和维护,确保产品的稳定性和可靠性。
2.请谈谈你的开发经验。
答案:我拥有丰富的开发经验,在多个项目中担任过主要开发者和技术负责人。
我能够使用多种编程语言和框架,包括Java、Python、Ruby、Node.js等等。
我也精通多个数据库技术,如MySQL、Oracle、MongoDB等等。
我还有很强的算法和数据结构能力,能够解决复杂的问题。
3.请谈谈你对软件开发的理解。
答案:我认为软件开发不仅仅是编写代码,还需要深入理解业务需求,并将其转化为技术实现方案。
软件开发需要不断学习和改进,关注技术趋势和最佳实践,保证代码的可维护性和扩展性。
同时,软件开发也需要与团队协作,包括产品经理、设计师、测试人员等等,确保项目的成功。
4.请谈谈你在代码质量方面的经验和思路。
答案:在我的工作中,我非常注重代码质量,包括可读性、可维护性、可扩展性和可测试性等方面。
我会使用代码规范和最佳实践来编写高质量的代码。
我还会使用单元测试和集成测试等技术来保证代码的质量和稳定性。
此外,我也会使用代码审查等工具来帮助发现潜在的问题。
5.请谈谈你对RESTful API的理解和使用经验。
答案:我对RESTful API有着深刻的理解和使用经验。
RESTful API是一种基于HTTP协议的API设计风格,它强调资源的URI和HTTP动词的使用。
我会遵循RESTful API的设计原则,使用标准的HTTP动词(GET、POST、PUT、DELETE等),并使用恰当的HTTP状态码和响应格式。
我也会使用Swagger等工具来生成API 文档和进行测试。
6.请谈谈你在数据库方面的经验和能力。
程序员的全部面试题及答案1. 简介在当今的技术领域中,程序员是非常重要的一群人才。
无论是在软件开发公司,还是在互联网企业,程序员都扮演着关键的角色。
为了获得理想的职位,程序员需要通过面试来展示他们的技术能力和知识水平。
本文将介绍一些常见的程序员面试题,并提供相应的答案作为参考。
2. 数据结构和算法2.1. 请解释什么是数据结构,以及常见的数据结构有哪些?数据结构是指数据的组织、存储和管理的方式。
常见的数据结构包括数组、链表、栈、队列、树、图等。
2.2. 请解释什么是算法,以及常见的算法有哪些?算法是指解决问题的一系列步骤和规则。
常见的算法有排序算法(如冒泡排序、快速排序)、查找算法(如二分查找)、图算法(如最短路径算法)等。
2.3. 请解释时间复杂度和空间复杂度分别是什么?时间复杂度是指执行算法所需时间的度量,通常用大O表示。
空间复杂度是指执行算法所需存储空间的度量,也是用大O表示。
2.4. 请给出冒泡排序算法的实现和时间复杂度。
冒泡排序是一种简单的排序算法,基本思想是比较相邻两个元素,如果顺序错误则交换位置。
重复进行该过程直至排序完成。
其时间复杂度为O(n^2)。
2.5. 请给出二分查找算法的实现和时间复杂度。
二分查找是一种在有序数组中快速查找目标元素的算法。
基本思想是比较目标值与数组中间元素的大小,然后决定继续在左半部分或右半部分进行查找。
其时间复杂度为O(logn)。
3. 编程语言相关问题3.1. 请列举几种常见的编程语言,并简单介绍它们的特点。
常见的编程语言包括C、C++、Java、Python、JavaScript等。
C语言是一种高效的系统编程语言,C++是C的扩展,支持面向对象编程。
Java是一种跨平台的编程语言,具有良好的安全性和可移植性。
Python 是一种简洁、易读易写的脚本语言。
JavaScript是用于网页开发的脚本语言,用于增强网页的交互性和动态性。
3.2. 请解释什么是面向对象编程(OOP)?面向对象编程是一种编程范式,它将数据和操作数据的方法封装在一起,将程序看做是对象的集合。
程序员面试最常问的10个问题解析求职者求职应聘过程中,面试是最关键的一步,是求职者能否顺利签约的重要环节。
那关于程序员面试常问的问题都是一个套路,熟悉后也就懂得其中的回答技巧了。
下面是店铺为你整理的程序员面试常问问题,希望对你有帮助。
程序员面试最常问的问题1.你最喜欢的编程语言是什么?2.你讨厌哪些编程语言?为什么?3.如果让你在自己最常用的编程语言上面添加功能,你希望是什么功能?4.说一个你曾经参与过的项目,在这过程中经历了哪些困难,最后如何克服? 你有没有干过什么事情最后却铩羽而归?5.在某个休息天,突然有同事打电话来要你快速回复有关于你最近写的代码片段的问题,你会不会觉得生气烦躁?6.你被要求去搞定一堆艰巨的代码,但是你却不知道它是如何工作的,没有文档也没有测试,你会怎么做?7.在zelda系列中你最喜欢什么游戏?你还喜欢哪些?你8.是否曾想过如果是你先开发的minecraft,那会怎么样?9.你喜欢什么网站? 你会推荐什么书作为必读?10.最后一个但并非是最不重要的,请解释以下名词:dry、solid、yagni、乐观锁与悲观锁)、mvc与mvvm(可自行添加)此外,写代码能力也是不可忽视的。
可以让他们展示自己写的代码或者实现一个你现场要求的功能。
真正有能力的程序员会为自己的代码感到骄傲,所以可以好好观察一下,看看他们是否乐意并勇于展示自己的代码。
面试的技巧与注意事项亲友团:不带为妙在应聘面试时,“亲友团”还是不带为妙。
千万不要以“情侣档”或父母陪同的方式求职,这样会让考官认为你依赖性太强、独立性太差,继而对你的能力产生怀疑。
微笑:始终如一做好面试前的形象准备,掌握面试礼仪全攻略,微笑应贯穿应聘全过程。
应聘者进了公司,从跟前台打交道开始,就不妨以笑脸示人。
见到面试官之后,不管对方是何种表情,都要微笑着与其握手、自我介绍。
在面试过程中,也要始终注意,不要让面部表情过于僵硬,要适时保持微笑。
1.设置地址为0x67a9的整型变量的值为0xaa66int *ptr;ptr = (int *)0x67a9;*ptr = 0xaa66;说明:这道题就是强制类型转换的典型例子,无论在什么平台地址长度和整型数据的长度是一样的,即一个整型数据可以强制转换成地址指针类型,只要有意义即可。
2.函数传参获取数组长度的方法template <typename T, int N>void printlen(T (&c)[N]){cout<<"c[]length: "<<sizeof(c)<<endl;cout<<N<<endl;}int main(int argc, char *argv[]){int p[]={1, 2, 3, 4, 5};printlen(p);}这是一种非类型模板形参,在需要常量表达式的时候可使用非类型模板形参。
如上例,当调用printlen 函数时编译器从数组实参中读取int N的值3.memset 和memcpy#include <cstring >memcpy原型:extern void *memcpy(void *dest, void *src, unsigned int count);功能:由src所指内存区域复制count个字节到dest所指内存区域。
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。
memset包含:extern void *memset(void *buffer, int c, int count);功能:把buffer所指内存区域的前count个字节设置成字符c。
说明:返回指向buffer的指针。
4. C++的空类有哪些成员函数缺省构造函数。
缺省拷贝构造函数。
缺省析构函数。
缺省赋值运算符。
缺省取址运算符。
缺省取址运算符const。
5. 写出float x 与“零值”比较的if语句。
if(x>0.000001&&x<-0.000001)6. Internet采用哪种网络协议?该协议的主要层次结构?Tcp/Ip协议主要层次结构为:应用层/传输层/网络层/数据链路层/物理层7.Internet物理地址和IP地址转换采用什么协议?ARP (Address Resolution Protocol)(地址解析協議)8.IP地址的编码分为哪俩部分?IP地址由两部分组成,网络号和主机号。
不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。
9.变量的声明和定义有什么区别为变量分配地址和存储空间的称为定义,不分配地址的称为声明。
一个变量可以在多个地方声明,但是只在一个地方定义。
加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。
10. sizeof和strlen的区别sizeof和strlen有以下区别:s izeof是一个操作符,strlen是库函数。
s izeof的参数可以是数据的类型,也可以是变量,而strlen只能以结尾为…\0…的字符串作参数。
编译器在编译时就计算出了sizeof的结果。
而strlen函数必须在运行时才能计算出来。
并且sizeof计算的是数据类型占内存的大小,而strlen计算的是字符串实际的长度。
数组做sizeof的参数不退化,传递给strlen就退化为指针了。
11. C中的malloc和C++中的new有什么区别malloc和new有以下不同:(1)new、delete 是操作符,可以重载,只能在C++中使用。
(2)malloc、free是函数,可以覆盖,C、C++中都可以使用。
(3)new 可以调用对象的构造函数,对应的delete调用相应的析构函数。
(4)malloc仅仅分配内存,free仅仅回收内存,并不执行构造和析构函数(5)new、delete返回的是某种数据类型指针,malloc、free返回的是void指针12.一个指针可以是volatile吗volatile类似于大家所熟知的const也是一个类型修饰符。
volatile是给编译器的指示来说明对它所修饰的对象不应该执行优化。
volatile的作用就是用来进行多线程编程。
可以,因为指针和普通变量一样,有时也有变化程序的不可控性。
常见例:子中断服务子程序修改一个指向一个buffer的指针时,必须用volatile来修饰这个指针13.static有什么用途?对于局部变量改变其生存期,对于全局变量改变其可见性主要从两个方面考虑:(1)静态存储:a. 函数体内static变量的作用范围为该函数体,该内存在静态数据区上分配且只被分配一次,下次再调用该函数时依然维持上一次的值。
b. 类中的static成员变量属于整个类所有,对类的所有对象只有一份拷贝c. 在类中的static成员函数属于整个类所拥有,这个函数不接受this指针,因而只能访问类的static成员变量。
(2)控制名字可见性a. 在模块内的static全局变量可以被模块内的所有函数访问,但是不能被模块外的其他函数访问b. 在模块内的static成员函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内。
14.引用与指针有什么区别1) 引用必须被初始化,指针不必。
2) 引用初始化以后不能被改变,指针可以改变所指的对象。
3) 不存在指向空值的引用,但是存在指向空值的指针。
15.描述实时系统的基本特性在特定时间内完成特定的任务,实时性与可靠性。
16. 简述C、C++程序编译的内存分配情况C、C++中内存分配方式可以分为三种:(1)从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。
速度快、不容易出错,因为有系统会善后。
例如全局变量,static变量等。
(2)在栈上分配:在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。
栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)从堆上分配:即动态内存分配。
程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在何时用free或delete释放内存。
动态内存的生存期由程序员决定,使用非常灵活。
如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块。
一个C、C++程序编译时内存分为5大存储区:堆区、栈区、全局区、文字常量区、程序代码区17. 谈谈你对拷贝构造函数和赋值运算符的认识拷贝构造函数和赋值运算符重载有以下两个不同之处:(1)拷贝构造函数生成新的类对象,而赋值运算符不能。
(2)由于拷贝构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验源对象是否和新建对象相同。
而赋值运算符则需要这个操作,另外赋值运算中如果原来的对象中有内存分配要先把内存释放掉注意:当有类中有指针类型的成员变量时,一定要重写拷贝构造函数和赋值运算符,不要使用默认的。
18. 不能被继承的类(1)构造函数private此时我们可以通过static成员函数获得该类的实例(我们只能得到位于堆上的实例)class FinalClass1{public :static FinalClass1* GetInstance(){return new FinalClass1;}static void DeleteInstance( FinalClass1* pInstance){delete pInstance;pInstance = 0;}private :FinalClass1() {}~FinalClass1() {}};(2)想法:实现一个和一般类除了不能被继承之外其他用法都一样的类template<typename T> class MakeFinal{friend T;private :MakeFinal() {}~MakeFinal() {}};class FinalClass2 : virtual public MakeFinal<FinalClass2>{public :FinalClass2() {}~FinalClass2() {}};此时FinalClass2就不能再被继承了,由于类FinalClass2 是从类MakeFinal <FinalClass2> 虚继承过来的,在调用Try 的构造函数的时候,会直接跳过FinalClass2 而直接调用MakeFinal <FinalClass2> 的构造函数。
(虚继承的一个特征就是虚基类的构造函数由最终子类负责构造)非常遗憾的是,Try 不是MakeFinal <FinalClass2> 的友元,因此不能调用其私有的构造函数。
基于上面的分析,试图从FinalClass2 继承的类,一旦实例化,都会导致编译错误,因此是FinalClass2 不能被继承。
这就满足了我们设计要求。
19. 访问基类的私有虚函数很好的题目,借这个题目学习虚函数。
解题思路就是:虽然不能通过对象调用这个虚函数,但是因为虚函数会在子类的那段内存中保存虚函数表的入口地址,拿到虚函数的地址就可以转换成函数指针来调用他。
下面主要解释这一行代码:pFun = ( Fun )*( ( int* ) * ( int* )( &b ) + i );(1)在子类内存空间中最开始(就是子类对象的地址&b)的地方存了一个指向虚函数表的指针(这里的最开始的说法应该是大多数编译器的做法),为了获得这个指向虚函数表的指针,需要做这个操作*(int*)&b,解释:对象b的地址强制转换成一个int指针(因为地址都是整型数),然后再解引用该指针获得虚表的指针值。
(2)再做一次(int*)获得虚表首地址的值,然后+i,每次+1都指向下一个虚函数的入口地址(3)最后(Fun),将虚函数入口地址强制转换为函数指针,用函数指针来完成这个私有虚函数的调用。
#include <iostream.h>class A{virtual void g() { cout << "A::g" << endl; }private:virtual void f(){ cout << "A::f" << endl; }};class B : public A{void g() { cout << "B::g" << endl; }virtual void h() { cout << "B::h" << endl; }};typedef void( *Fun )( void );void main(){B b;Fun pFun;for(int i = 0 ; i < 3; i++){pFun = ( Fun )*( ( int* ) * ( int* )( &b ) + i );pFun();}}20.类成员函数的重载、重写和隐藏成员函数被重载的特征(1)相同的范围(在同一个类中);(2)函数名字相同;(3)参数不同;(4)virtual 关键字可有可无。