【复习】C++知识点 您所在的位置:网站首页 进程间通信有哪些方法分别有哪些特点 【复习】C++知识点

【复习】C++知识点

2023-04-15 06:05| 来源: 网络整理| 查看: 265

1. C++类有哪些特性:

C++三大特性:继承、多态、封装

(1)继承: 一个对象直接使用另个对象的属性和方法

优点: 1.减少代码的重复量 2.继承是多态的前提 3.继承增加了类的耦合性

缺点:1.继承在编译阶段定义;无法在运行阶段改变父类继承的实现

2.父类通常至少定义了子类的部分行为,父类的改变都有可能影响子类的行为

3.如果继承下的子类不适合解决新问题,父类必须重写或替换,那么这种依赖关系就限制了灵活性,最终限制了复用性。

虚继承:为了解决多重继承中的二义性和数据冗余问题,维护了一张虚基表。

(2)多态。

C++中有两种多态,称为动多态(运行期多态)和静多态(编译期多态),而静多态主要通过模板来实现,宏也是实现静多态的一种途径。动多态在C++中是通过虚函数实现的,即在基类中存在一些接口(一般为纯虚函数),子类必须重载这些接口。这样通过使用基类的指针或者引用指向子类的对象,就可以实现调用子类对应的函数的功能。动多态的函数调用机制是执行期才能进行确定,所以它是动态的。

接口的多种不同实现方式即为多态。可以举个例子加深记忆,比如电脑的USB接口,既可以插优盘,又可以插鼠标,USB接口就类似类的接口。

优点: 1.大大提高了代码的可复用性; 2.提高了代码的可维护性,可扩充性;

缺点: 1.易读性比较不好,调试比较困难 2.模板只能定义在.h文件中,当工程大了之后,编译时间十分的变态

(3)封装。 隐藏对象的属性和实现细节,仅仅对外提供接口和方法。

优点:1)隔离变化;2)便于使用;3)提高重用性;4)提高安全性缺点:1)如果封装太多,影响效率;2)使用者不能知道代码具体实现。

重载(overload)VS 覆盖(override):

重载:写一个与已有函数同名但是参数表不同的函数;

覆盖:虚函数总是在派生类中被改写。

2.C++的引用与C的指针有什么区别

语法概念层面:引用变量只是别名,没有实际空间,与其实体共用同一块内存(有区别) 底层实现上:引用就是指针,引用实际上是有空间-----------地址(无区别)

1.引用在定义时必须初始化,指针没有要求。

2.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体。

Int* pa=&a; Int* const p=&a; Pa=&b; 错

3.没有NULL 引用,但有NULL指针。

4.在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)

5.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小。

6.有多级指针,但是没有多级引用。

7.访问实体方式不同,指针需要显示解引用,引用编译器自己处理。

int main() { int a = 10; int b = 20; int& ra = a; int* ra = 20; int* pa = &a; *pa = 20; return 0; }

8.引用比指针使用起来相对更安全。

3.多态、重载、返回值不同是不是重载(C++不能被重载的运算符有?)

重载 : 同名不同参。 重写,子类重写父类的方法重载必须改变参数列表(否则,虚拟机怎么知道该调用哪一个方法)

相同点:方法的重载和重写都是实现多态的方式

不同点: 1,重写必须继承,重载不用, 2,重写的方法名,参数数目相同,参数类型兼容,重载的方法名相同,参数列表不同。 3,重写的方法修饰符大于等于父类的方法,重载和修饰符无关。 4,重写不可以抛出父类没有抛出的一般异常,可以抛出运行时异常。 相同参数不同返回值不可以重载。

不能被重载的运算符只有五个,分别是

“.”(成员访问运算符)

*(成员指针访问运算符)

:: (域运算符)

sizeof (长度运算符)

?: (条件运算符)

前两个运算符不能重载是为了保证访问成员的功能不被改变 ,域运算符和sizeof运算符的运算对象是类型而不是变量或者一般表达式,不具备重载的特征。

4. 抽象类 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。比如,在一个图形编辑软件的分析设计过程中,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域并不是直接存在的,它就是一个抽象概念。而正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。

抽象类具有以下特性: ● 抽象类不能实例化。 ● 抽象类可以包含抽象方法和抽象访问器。 ● 不能用 sealed 修饰符修饰抽象类,因为这两个修饰符的含义是相反的。 采用 sealed 修饰符的类无法继承,而 abstract 修饰符要求对类进行继承。 ● 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。

5.32位系统下sizeof(void*)-----指针大小依赖平台,32位平台下4个字节 6.结构体内存对齐原则 第一个成员在与结构体变量偏移量为0的地址处。其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8 Linux中的默认值为4结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

32位编译器 char :1个字节 char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器) short int : 2个字节 int: 4个字节 unsigned int : 4个字节 float: 4个字节 double: 8个字节 long: 4个字节 long long: 8个字节 unsigned long: 4个字节

64位编译器 char :1个字节 char*(即指针变量): 8个字节 short int : 2个字节 int: 4个字节 unsigned int : 4个字节 float: 4个字节 double: 8个字节 long: 8个字节 long long: 8个字节 unsigned long: 8个字节

为什么存在内存对齐?

平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

● 总体来说: 结构体的内存对齐是拿空间来换取时间的做法。 那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到: 让占用空间小的成员尽量集中在一起。

7.预处理,编译,汇编,链接四个阶段分别经历了什么 预处理:替换代码中的预处理命令(宏定义就是在这里直接替换的,头文件导入)编译:对代码按执行顺序进行编译成.o或.obj目标文件对预处理后的代码进行翻译工作,得到计算机所认识的格式编译工作得到的结果文件叫做目标文件。扩展名是.o(编译得到汇编文件(.s) ->经过汇编后得到.o目标文件)汇编:将其他高级语言转换成机器语言链接:代码中的各种调用关系重定位、把所有的目标文件和其他必要的文件合并在一起得到最终的可执行文件 8. 进程与线程的区别; 进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。 9.对比常见进程间通信方式的优缺点

进程间通信方式: 管道,消息队列,共享内存,信号量,socket,信号,文件锁

1.管道

匿名管道: 概念:在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,一般使用fork函数实现父子进程的通信。命名管道: 概念:在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,没有血缘关系的进程也可以进程间通信。特点: 1.面向字节流, 2.生命周期随内核 3.自带同步互斥机制。 4.半双工,单向通信,两个管道实现双向通信。

2,消息队列

概念:在内核中创建一队列,队列中每个元素是一个数据报,不同的进程可以通过句柄去访问这个队列。

消息队列提供了⼀个从⼀个进程向另外⼀个进程发送⼀块数据的⽅法。

每个数据块都被认为是有⼀个类型,接收者进程接收的数据块可以有不同的类型值

消息队列也有管道⼀样的不⾜,就是每个消息的最⼤⻓度是有上限(MSGMAX), 每个消息队 列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有⼀个上限(MSGMNI)

特点: 1.消息队列可以认为是一个全局的一个链表,链表节点存放着数据报的类型和内容,有消息队列的标识符进行标记。 2.消息队列允许一个或多个进程写入或者读取消息。 3.消息队列的生命周期随内核。 4.消息队列可实现双向通信。

3,信号量

概念 : 在内核中创建一个信号量集合(本质是个数组),数组的元素(信号量)都是1,使用P操作进行-1,使用V操作+1,

P(sv):如果sv的值⼤大于零,就给它减1;如果它的值为零,就挂起该进程的执⾏.

V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运⾏,如果没有进程因等待sv⽽挂起,就给它加1。

PV操作用于同一进程,实现互斥。 PV操作用于不同进程,实现同步。

功能:对临界资源进行保护。

4,共享内存

概念: 将同一块物理内存一块映射到不同的进程的虚拟地址空间中,实现不同进程间对同一资源的共享。

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。

特点: 1.不用从用户态到内核态的频繁切换和拷贝数据,直接从内存中读取就可以。 2.共享内存是临界资源,所以需要操作时必须要保证原子性,使用信号量或者互斥锁都可以。因此,共享内存都和信号量一起使用。 3.生命周期随内核。

5.套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。

参考链接:https://blog.csdn.net/wm12345645/article/details/82381407



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有