c++类与对象
1.介绍一下面相对象的三大特性
答:
1.封装
2.继承
3.多态
多态分为静态多态和动态多态。
静态多态:常见的有函数重载和模板
函数重载简单说,在函数参数类型和个数不同的情况下,一个函数名可以用许多次。
模板:可以按照传入的参数类型调用不同的方法。
缺点是比较死板,必须提前知道参数的类型和个数或者提前知道模板被什么样的类型使用。
动态多态
通过虚函数和继承来根据不同的对象来调用不同子类重写父类的虚函数。适用于用同一个规范,但是要按照不同的对象类型来调用不同方法的情况。
其中虚函数的开销是1.虚函数表 2.虚函数表指针 3.动态的绑定过程
1.虚函数表:有虚函数或重写了虚函数的类会创建一个虚函数表,里面存储了所有该类虚函数的地址。
2.虚函数指针: 这个指针指向了该对象所对应的虚函数表,在每个对象的前8个字节存储。
3.动态绑定的过程:
动态绑定过程: 如:当用Animal* a = new Dog()时: 创建Dog对象时,会设置a->vptr指向Dog类的vtable。
当调用a->speak(),程序会通过vptr找到Dog类的vtable,调用里边的speak()地址。
c++网络编程
1.请解释ET(edge-triggered)和LT(level-triggered)
LT(Level-Triggered,水平触发)
工作方式:当文件描述符处于就绪状态时,系统会持续通知你。
-
特点:收到数据后,没读完之前会反复发送通知
-
举例:
-
假设 socket 接收缓冲区有数据可读(>0 字节)
-
操作系统会一直通知你"有数据可读"
-
即使你只读取了一部分数据,只要缓冲区还有数据,下次调用
epoll_wait()时还会收到通知
-
ET(Edge-Triggered,边缘触发)
工作方式:只在文件描述符状态发生变化时通知一次。
-
特点:只在状态变化的"边缘"触发通知
-
举例:
-
当 socket 从"无数据"变为"有数据"时,只通知一次
-
如果你没有一次性读取完所有数据,剩余的数据不会触发新通知
-
直到有新的数据到达(状态再次变化),才会再次通知
-
2.请你说一下为什么LT可以支持阻塞io,而ET不行呢?
阻塞IO:
这里阻塞io指的是如果要读这个数据,程序会一直等待,就算没有数据,程序也不会做其他事。非阻塞io是他会正常读取,如果此时没有数据读,他会返回false。这样就提高了cpu的利用率。
答:
ET是必须一次性将数据读完的,因为epoll只给他发一次信号。
1.但是read函数需要EAGAIN错误码(表示当前没有数据可读)来知道自己有没有读完的。 而EAGAIN是非阻塞专有的。所以必须使用非阻塞io,来保证ET的正确执行。
2.并且如果用阻塞io,会导致死锁问题,read在等待新数据到来,但是此时卡住了,哪怕新数据到来也无法给他通知。
注:为什么只有非阻塞io才有EAGAIN错误码? 因为这就是他们的设计理念,阻塞io要的就是一直等待,等待到有数据。 但是非阻塞io,需要一个错误码或者返回值来告诉当前缓冲区无法读取,为什么无法读取。