7.18、面试回顾

1、c++特性

1) 封装、继承、多态

a) 封装是为了代码模块化和增加安全性
保护数据成员,不让类以外的程序直接访问或者修改类的成员,只能通过其成员对应方法访问(即数据封装)
隐藏方法实现的具体细节,仅仅提供接口,内容修改不影响外部调用(即方法封装)

private:只能由1.该类中的函数、2.其友元函数访问。
不能被任何其他访问,该类的对象也不能访问。
protected:可以被1.该类中的函数、2.子类的函数、3.其友元函数访问。
但不能被该类的对象访问。
public:可以被1.该类中的函数、2.子类的函数、3.其友元函数访问,也可以由4.该类的对象访问。

b) 继承的目的: 重用代码一个类B继承另一个类A,则B就继承了A中申明的成员以及函数
派生的目的: 代码扩展,继承自一个类然后添加自己的属性和方法则实现代码的扩展
c) 多态: 接口的复用,一个接口多种实现
用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数

2) c++class和C语言struct的区别

a) C++ 中保留了C语言的 struct 关键字,并且加以扩充。
b) 在C语言中,struct 只能包含成员变量,不能包含成员函数。而在C++中,struct 类似于 class,既可以包含成员变量,又可以包含成员函数。

C++中的 struct 和 class 基本是通用的,唯有几个细节不同
a) 使用 class 时,类中的成员默认都是 private 属性的;而使用 struct 时,结构体中的成员默认都是 public属性的。
b) class 继承默认是 private 继承,而 struct 继承默认是 public 继承。
c) class 可以用在模板参数中,而struct 不能。

3) 析构函数、虚析构函数、纯虚析构函数

对象在结束其生命周期之前,都会调用析构函数以完成必要的清理工作;派生类调用的析构函数顺序是“先子类,后基类”;

普通析构函数:
1、若delete运算符删除的是子类指针对象,则会调用子类和基类的析构函数;
2、若析构函数是非虚的,即使基类指针指向的是子类对象,则delete 指针对象时,也仅调用基类的析构函数
虚析构函数:
当基类的析构函数为虚函数时,基类指针指向的是子类对象时,使用delete运算符删除指针对象,析构函能够按照“先子类,后基类”的原则完成对象清理;这样在多重继承的类中,能够保证每个类都能够得到正确的清理;比如基类和子类的缓冲区都能被释放;

4)#include “filename.h”和#include < filename.h>的区别

答:对于#include <filename.h>编译器从标准库开始搜索filename.h
对于#include “filename.h”编译器从用户工作路径开始搜索filename.h

2、静态链接库和动态链接库

a) 静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”。
b) 静态库在编译时会直接整合到目标程序中,编译成功的可执行文件可独立运行;动态库在编译时不会放到连接的目标程序中,即可执行文件无法单独运行。
c) 静态库的缺点:利用静态库编译成的文件比较大;升级难度没有明显优势,如果函数需要更新,需要重新编译;
d) 动态函数库在编译的时候,在程序里只有一个“指向”的位置而已,也就是说当可执行文件需要使用到函数库的机制时,程序才会去读取函数库来使用;从产品功能升级角度方便升级,只要替换对应动态库即可,不必重新编译整个可执行文件。
e) 综上,不能看出:从产品化的角度,发布的算法库或功能库尽量使动态库,这样方便更新和升级,不必重新编译整个可执行文件,只需新版本动态库替换掉旧动态库即可。

1) 动态链接和静态链接

扩展:静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法。链接器是一个独立程序,将一个或多个库或目标文件(先前由编译器或汇编器生成)链接到一块生成可执行程序。静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。

动态链接所调用的函数代码并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息(往往是一些重定位信息)。仅当应用程序被装入内存开始运行时,在Windows的管理下,才在应用程序与相应的DLL之间建立链接关系。当要执行所调用DLL中的函数时,根据链接产生的重定位信息,Windows才转去执行DLL中相应的函数代码。

2)QT中引入SDK开发包的原理讲解

原理简介:头文件(.h)、源文件(.c)、库文件(.lib .dll)
1.头文件(,h):声明函数接口,一些函数方法名
2.源文件(.c):对头文件中函数的实现源代码
3. .lib库文件有两种:
(1)静态链接库(静态库):把程序中调用的某函数的相关模块链接在一起,然后放入内存进行执行。
(2)动态链接库(导入库):把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行时再从DLL中寻找相应函数代码进行执行。
所以.lib库就是导入.dll文件用的。
4. .dll库文件:
含有函数的可执行代码;与.c文件的源代码的关系是:.c的源代码编译封装之后就形成.dll文件

综上所述,这几个文件调用关系大致为:当我们在自己的程序中引用了一个H文件里的函数,编链器怎么知道该调用哪个.dll文件呢?这就是.lib文件的作用: 告诉链接器 调用的函数在哪个.dll模块中,函数执行代码在.dll中的什么位置,这也就是为什么需要 ”附加依赖项“ .lib文件,它起到连接的桥梁作用。

.h头文件是编译时必须的,lib库是链接时需要的,dll动态链接库是运行时需要的。
特此鸣谢,转载此处

3、常用的设计模式

1) 单例模式

a) 私有化它的构造函数,以防止外界创建单例类的对象;
b) 使用类的私有静态指针变量指向类的唯一实例;
c) 使用一个公有的静态方法获取该实例。

class Singleton
{
private:
	static Singleton* instance;
private:
	Singleton() {};
	~Singleton() {};
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
public:
	static Singleton* getInstance() 
        {
		if(instance == NULL) 
			instance = new Singleton();
		return instance;
	}
};
 
// init static member
Singleton* Singleton::instance = NULL;

通过加锁避免:两个以上线程调用GetInstance(),同时监测到instance为null的情况;

2)工厂模式

工厂模式:子类对象用相同的父类模块方法,不同的子类分别实现模块方法中的抽象方法,从而实例化不同的子类对象(父类提供抽象方法,继承了的子类自己各自慢慢写怎么叫,怎么飞)。

3) 策略模式和工厂模式区别

它们的用途不一样。简单工厂模式是创建型模式,它的作用是创建对象。策略模式是行为型模式,作用是在许多行为中选择一种行为,关注的是行为的多样性。
(简单来说,工厂模式就是英语考试的完形填空题(自己考虑填什么词、句子),策略模式就是信息匹配题(提前写好选择项,当你有多个填空时,直接选就好了,没有适合的就再多写几个选择项))

4、指针与引用

值传递、引用传递、指针传递

指针和引用的区别:

1 指针有自己的一块空间(指针所指向的地址需要存放数据的时候需要申请空间),而引用只是一个别名;(本质)
2 使用sizeof看一个指针的大小是4(32位下),而引用则是被引用对象的大小; (大小)
3 指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象 的引用;(初始化)
4 作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引 用的修改都会改变引用所指向的对象;
5 可以有const指针,但是没有const引用;
6 指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能被改变;
补充:
7、指针可以有多级指针(**p),而引用至多一级;
8、指针和引用使用++运算符的意义不一样;
9、如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄露。

5、内存的分配方式有几种?

1、静态存储区域分配,内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量、静态变量
2、在栈上创建,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
3、在堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
4、文字常量区,常量字符串就是放在这里的,程序结束后由系统释放。
5、程序代码区,存放函数体的二进制代码。

6、STL容器

Vector(后面的类型莫忘)

1、什么是vector?

向量(vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。

2、容器特性

1.顺序序列
顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。
2.动态数组
支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。操供了在序列末尾相对快速地添加/删除元素的操作。
3.能够感知内存分配器的(Allocator-aware)
容器使用一个内存分配器对象来动态地处理它的存储需求。

3、常用操作

1、 构造
vector v1; //默认构造 无参数

int arr[] = { 20,10,23,90 };
vector v2(arr,arr+sizeof(arr);//使用数组对vector进行初始化 参数:起始地址、长度
vector v3(v2.begin(), v2.end());//使用向量对vector进行初始化 参数:向量起始地址、向量末地址
vector v4(v3); //使用其他向量对vector进行初始化 参数:vector
2、 赋值操作
Vector v2;
V2.assaign(v1.begin(), v1.end()); //使用向量对vector进行赋值 参数:起始地址、末地址

vector v3;
v3 = v2;//=号操作符重载

int arr1[] = { 200,100,300,400 };
vector v4(arr1, arr1 + sizeof(arr1) / sizeof(int));
v4.swap(v1); //使用swap函数

3、 常用函数
resize(int n,element) ;将容器的大小设为n,扩容后的每个元素的值都为element
v1[i]、v1.at(i)、v1.front()、v1.back():取值操作
v1.insert(v1.begin(), 2, 1000); 在指定位置loc前插入num个值为val的元素

map

1、什么是map?

C++ 中 map 提供的是一种键值对容器,里面的数据都是成对出现的,如下图:每一对中的第一个值称之为关键字(key),每个关键字只能在 map 中出现一次;第二个称之为该关键字的对应值。

2、常用操作

1、 插入操作
m.insert(pair<int, int>(1, 10)); //插入pair
m.insert(make_pair<int, int>(2, 20));
m[4] = 40;

2、 查找操作
map<int,int> ::iterator pos = m.find(3);
if (pos != m.end()) // true为元素存在,false元素不存在

3、 删除操作
iterator erase(iterator it) ;//通过一个条目对象删除
iterator erase(iterator first,iterator last); //删除一个范围
size_type erase(const Key&key); //通过关键字删除
clear();//就相当于enumMap.erase(enumMap.begin(),enumMap.end());

7、多线程

7.1、多线程和多进程的区别

1)进程是资源分配的最小单位,线程是CPU调度的最小单位
2)在这里插入图片描述

7.2、Qt程序主界面运行卡断如何解决

原因:显示数据和处理数据放在同一个线程中处理
做法:将读取处理数据和显示数据两个步骤分离,这属于异步操作(同步:等待数据处理接口的返回值)
异步:线程间相互排斥的使用临界资源的现象,就叫互斥。
同步:线程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系。

7.3、多线程通线(共享内存和消息传递)

1、volatile关键字来实现线程间通信是使用共享内存的思想。程序中运用的方式大致意思是多个线程同时监听一个变量,当这个变量发生变化的时候,线程能偶感知来执行相应的业务。
2、QT中常用信号与槽,来实现跨线程通信。跨线程的信号与槽使用自定义类型时,使用qRegisterMetaType对自定义类型进行注册。

7.4、Qt信号与槽的链接方式

1、Qt::DirectConnection:槽函数会在信号发送的时候直接被调用(本质:槽函数运行于信号发送者所在的线程),多线程环境下比较危险,可能会造成崩溃。
2、Qt::QueuedConnection:槽函数在控制回到接收者所在线程的事件循环时被调用(本质:槽函数运行于信号接收者所在的线程的事件循环时被调用),多线程环境下一般用这个。

7.5、多进程通信

六种进程间通信方式

7.6、TCP与UDP的区别

TCP与UDP的区别

7.6、请详细介绍一下TCP 的三次握手机制

位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)Sequence number(顺序号码) Acknowledge number(确认号码)
思路:TCP连接的三次握手机制,最重要的知识点,必须得会,通讯过程以及客户端、服务器的对应的状态都需要记住哈。
TCP提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的就是同步连接双方的序列号和确认号并交换TCP窗口大小信息。我们一起来看下流程图哈:
在这里插入图片描述
TCP三次握手
第一次握手(SYN=1, seq=x),发送完毕后,客户端就进入SYN_SEND状态
第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1), 发送完毕后,服务器端就进入SYN_RCV状态。
第三次握手(ACK=1,ACKnum=y+1),发送完毕后,客户端进入ESTABLISHED状态,当服务器端接收到这个包时,也进入ESTABLISHED状态。

7.7、TCP握手为什么是三次,为什么不能是两次?不能是四次?

思路:TCP握手为什么不能是两次,为什么不能是四次呢?为了方便理解,我们以男孩子和女孩子谈恋爱为例子:两个人能走到一起,最重要的事情就是相爱,就是我爱你,并且我知道,你也爱我,接下来我们以此来模拟三次握手的过程:
在这里插入图片描述
为什么握手不能是两次呢?
如果只有两次握手,女孩子可能就不知道,她的那句我也爱你,男孩子是否收到,恋爱关系就不能愉快展开。
为什么握手不能是四次呢?
因为握手不能是四次呢?因为三次已经够了,三次已经能让双方都知道:你爱我,我也爱你。而四次就多余了。

7.8、说说TCP四次挥手过程

思路:TCP的四次挥手,也是最重要的知识点,一般跟三次握手会一起考的,必须得记住。
在这里插入图片描述

TCP四次挥手过程
第一次挥手(FIN=1,seq=u),发送完毕后,客户端进入FIN_WAIT_1状态。
第二次挥手(ACK=1,ack=u+1,seq =v),发送完毕后,服务器端进入CLOSE_WAIT状态,客户端接收到这个确认包之后,进入FIN_WAIT_2状态。
第三次挥手(FIN=1,ACK1,seq=w,ack=u+1),发送完毕后,服务器端进入LAST_ACK状态,等待来自客户端的最后一个ACK。
第四次挥手(ACK=1,seq=u+1,ack=w+1),客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入TIME_WAIT状态,等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入CLOSED状态。服务器端接收到这个确认包之后,关闭连接,进入CLOSED状态。

7.9、 TCP挥手为什么需要四次呢?

思路:TCP挥手为什么需要四次呢?为了方便大家理解,再举个生活的例子吧。
在这里插入图片描述

★小明和小红打电话聊天,通话差不多要结束时,小红说,“我没啥要说的了”。小明回答,“我知道了”。但是小明可能还有要说的话,小红不能要求小明跟着她自己的节奏结束通话,于是小明可能又叽叽歪歪说了一通,最后小明说,“我说完了”,小红回答,“我知道了”,这样通话才算结束。”

7.10、TCP四次挥手过程中,为什么需要等待2MSL,才进入CLOSED关闭状态

思路:这个问得频率特别高。去面试前,一定要把这道题拿下哈。
在这里插入图片描述

2MSL,two Maximum Segment Lifetime,即两个最大段生命周期。假设主动发起挥手的是客户端,那么需要2MSL的原因是:
★1.为了保证客户端发送的最后一个ACK报文段能够到达服务端。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的服务端就收不到对已发送的FIN + ACK报文段的确认。服务端会超时重传这个FIN+ACK 报文段,而客户端就能在 2MSL 时间内(超时 + 1MSL 传输)收到这个重传的 FIN+ACK 报文段。接着客户端重传一次确认,重新启动2MSL计时器。最后,客户端和服务器都正常进入到CLOSED状态。2. 防止已失效的连接请求报文段出现在本连接中。客户端在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。”

8、C++11新特性

C++11新特性梳理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值