| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> C++学习笔记 -> 正文阅读 |
|
[网络协议]C++学习笔记 |
????????根据派生的权限、基类中定义的权限,在派生类的类内和类外不同访问时的组合情况,列出下表:
????????注意,我们这里说的是基类的 private 成员不能在派生类中使用,并没有说基类的 private 成员不能被继承。实际上,基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,导致无法使用罢了。private 成员的这种特性,能够很好的对派生类隐藏基类的实现,以体现面向对象的封装性。 ????????创建派生类在调用自己的构造函数之前,会先调用基类的构造函数。 ????????派生类和基类的构造函数会自动调用,调用顺序是先调用基类的构造函数再调用的派生类构造函数。 ????????注意:一旦基类中有带参数的构造函数,派生类中则必须有显式传参的派生类构造函数,来实现基类中参数的传递,完成初始化工作。 ????????析构函数的调用顺序与构造函数则完全相反。 ????????构造函数调用顺序:基类->派生类 ????????析构函数调用顺序:派生类->基类 ????????构造函数的调用顺序: ????????基类构造函数总是被优先调用,这说明创建派生类对象时,会先调用基类构造函数,再调用派生类构造函数,如果继承关系有好几层的话,例如:A --> B --> C;那么创建C类对象时构造函数的执行顺序为:A类构造函数-->B类构造函数--> C类构造函数。构造函数的调用顺序是按照继承的层次自顶向下、从基类再到派生类的。 ????????派生类构造函数中只能调用直接基类的构造函数,不能调用间接基类的。 ????????在虚继承中,虚基类是由最终的派生类初始化的,换句话说,最终派生类的构造函数必须要调用虚基类的构造函数。对最终的派生类来说,虚基类是间接基类,而不是直接基类。这跟普通继承不同,在普通继承中,派生类构造函数中只能调用直接基类的构造函数,不能调用间接基类的。 ????????类其实也是一种数据类型,也可以发生数据类型转换,不过这种转换只有在基类和派生类之间才有意义,并且只能将派生类赋值给基类,包括将派生类对象赋值给基类对象、将派生类指针赋值给基类指针、将派生类引用赋值给基类引用,这在 C++ 中称为向上转型(Upcasting)。相应地,将基类赋值给派生类称为向下转型(Downcasting)。 ????????面向对象程序设计语言有封装、继承和多态三种机制,这三种机制能够有效提高程序的可读性、可扩充性和可重用性。 ????????“多态”指的是同一名字的事物可以完成不同的功能。多态可以分为编译时的多态和运行时的多态。前者主要是指函数的重载(包括运算符的重载)、对重载函数的调用,在编译时就能根据实参确定应该调用哪个函数,因此叫编译时的多态;而后者则和继承、虚函数等概念有关,是本章要讲述的内容。本教程后面提及的多态都是指运行时的多态。 ????????C++提供多态的目的是:可以通过基类指针对所有派生类(包括直接派生和间接派生)的成员变量和成员函数进行“全方位”的访问,尤其是成员函数。如果没有多态,我们只能访问成员变量。同一条语句可以执行不同的操作,看起来有不同表现方式,这就是多态。 ????????构成多态的条件:
????????静态联编:函数重载、函数模板的实例化 ????????动态联编:在运行的时候,才能确认执行哪段代码。 ????????静态联编由于编译时候就已经确定好怎么执行,因此执行起来效率高;而动态联编想必虽然慢一些,但优点是灵活。 ????????虚函数:
????????C++中虚函数的唯一用处就是构成多态。 ????????抽象类:virtual 返回值类型 函数名 (函数参数) = 0;
????????包含纯虚函数的类称为抽象类。之所以说它抽象,是因为它无法实例化,也就是无法创建对象。原因很明显,纯虚函数没有函数体,不是完整的函数,无法调用,也无法为其分配内存空间。抽象类通常是作为基类,让派生类去实现纯虚函数。派生类必须实现纯虚函数才能被实例化。 ????????函数重载:参数列表不同包括参数的个数不同、类型不同或顺序不同,仅仅参数名称不同是不可以的。函数返回值也不能作为重载的依据。 ????????函数重载规则:
????????运算符重载格式:
????????运算符重载注意:
????????类只是一个模板(Template),编译后不占用内存空间,所以在定义类时不能对成员变量进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了。 ????????类本身不占用内存空间,而变量的值则需要内存来存储。 ????????使用new在堆上创建出来的对象是匿名的,没法直接使用,必须要用一个指针指向它,再借助指针来访问它的成员变量或成员函数。 ????????一个类必须有构造函数,要么用户自己定义,要么编译器自动生成。一旦用户自己定义了构造函数,不管有几个,也不管形参如何,编译器都不再自动生成。 ????????static成员变量不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问。 ????????静态成员变量必须初始化,而且只能在类体外进行。 ????????静态成员函数与普通成员函数的根本区别:普通成员函数有this指针,可以访问类中的任意成员;而静态成员函数没有this指针,只能访问静态成员(包括静态成员变量和静态成员函数)。 ????????成员函数中出现的 this 指针,就是指向成员函数所作用的对象的指针。因此,静态成员函数内部不能出现 this 指针。成员函数实际上的参数个数比表面上看到的多一个,多出来的参数就是 this 指针。 ????????每个对象有各自的一份普通成员变量,但是静态成员变量只有一份,被所有对象所共享。静态成员函数不具体作用于某个对象。即便对象不存在,也可以访问类的静态成员。静态成员函数内部不能访问非静态成员变量,也不能调用非静态成员函数。 ????????常量对象上面不能执行非常量成员函数,只能执行常量成员函数。 ????????const 成员和引用成员必须在构造函数的初始化列表中初始化(无法在构造函数内部使用赋值方式初始化),此后值不可修改。 ????????引用必须在定义的同时初始化,并且以后也要从一而终,不能再引用其它数据,这有点类似于常量(const 变量)。 ????????友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。 ????????友元的关系是单向的而不是双向的。如果声明了类 B 是类 A 的友元类,不等于类 A 是类 B 的友元类,类 A 中的成员函数不能访问类 B 中的 private 成员。 ????????友元的关系不能传递。如果类 B 是类 A 的友元类,类 C 是类 B 的友元类,不等于类 C 是类 A 的友元类。 ????????除非有必要,一般不建议把整个类声明为友元类,而只将某些成员函数声明为友元函数,这样更安全一些。 ????????C++中struct和class区别:
????????对象所占用的存储空间的大小等于各成员变量所占用的存储空间的大小之和(如果不考虑成员变量对齐问题的话)。 ????????将对象所持有的其它资源一并拷贝的行为叫做深拷贝,我们必须显式地定义拷贝构造函数才能达到深拷贝的目的。 ????????如果一个类拥有指针类型的成员变量,那么绝大部分情况下就需要深拷贝,因为只有这样,才能将指针指向的内容再复制出一份来,让原有对象和新生对象相互独立,彼此之间不受影响。如果类的成员变量没有指针,一般浅拷贝足以。另外一种需要深拷贝的情况就是在创建对象时进行一些预处理工作,比如统计创建过的对象的数目、记录对象创建的时间等。 ????????网络连接也是一个文件,它也有文件描述符! ????????流格式套接字(SOCK_STREAM):流格式套接字(Stream Sockets)也叫“面向连接的套接字”。SOCK_STREAM 是一种可靠的、双向的通信数据流,数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送。浏览器所使用的 http 协议就基于面向连接的套接字,因为必须要确保数据准确无误,否则加载的 HTML 将无法解析。 ????????TCP 用来确保数据的正确性,IP(Internet Protocol,网络协议)用来控制数据如何从源头到达目的地,也就是常说的“路由”。 ????????数据报格式套接字(SOCK_DGRAM):数据报格式套接字(Datagram Sockets)也叫“无连接的套接字”。因为数据报套接字所做的校验工作少,所以在传输效率方面比流格式套接字要高。数据报套接字是一种不可靠的、不按顺序传递的、以追求速度为目的的套接字。数据报套接字也使用 IP 协议作路由,但是它不使用 TCP 协议,而是使用 UDP 协议(User Datagram Protocol,用户数据报协议)。QQ 视频聊天和语音聊天就使用 SOCK_DGRAM 来传输数据,因为首先要保证通信的效率,尽量减小延迟。 ????????OSI 7层网络模型:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。OSI 只是存在于概念和理论上的一种模型,它的缺点是分层太多,增加了网络工作的复杂性,所以没有大规模应用。 ????????TCP/IP 模型:接口层、网络层、传输层和应用层。 ????????程序一般都是通过应用层来访问网络的,程序产生的数据会一层一层地往下传输,直到最后的网络接口层,就通过网线发送到互联网上去了。数据每往下走一层,就会被这一层的协议增加一层包装,等到发送到互联网上时,已经比原始数据多了四层包装。当另一台计算机接收到数据包时,会从网络接口层再一层一层往上传输,每传输一层就拆开一层包装,直到最后的应用层,就得到了最原始的数据,这才是程序要使用的数据。给数据加包装的过程,实际上就是在数据的头部增加一个标志(一个数据块),表示数据经过了这一层,我已经处理过了。给数据拆包装的过程正好相反,就是去掉数据头部的标志,让它逐渐现出原形。 ????????socket编程,是站在传输层的基础上,所以可以使用TCP/UDP协议,但是不能干「访问网页」这样的事情,因为访问网页所需要的http协议位于应用层。 ????????sockaddr是一种通用的结构体,可以用来保存多种类型的IP地址和端口号,而sockaddr_in用来保存IPv4地址的结构体。sockaddr_in6,用来保存IPv6地址。 ????????listen()只是让套接字进入监听状态,并没有真正接收客户端请求,listen()后面的代码会继续执行,直到遇到 accept()。accept()会阻塞程序执行(后面代码不能被执行),直到有新的请求到来。 ????????每个socket被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。发送端只有在收到对方的 ACK 确认包后,才会清空输出缓冲区中的数据。 ????????I/O缓冲区特点:
????????TCP套接字默认情况下是阻塞模式,也是最常用的,也可以更改为非阻塞模式。 ????????三次握手示意图:???????? ????????三次握手的关键是要确认对方收到了自己的数据包,这个目标就是通过“确认号(Ack)”字段实现的。计算机会记录下自己发送的数据包序号 Seq,待收到对方的数据包后,检测“确认号(Ack)”字段,看Ack = Seq + 1是否成立,如果成立说明对方正确收到了自己的数据包。 ????????四次挥手示意图: ????????TCP 是面向连接的传输协议,建立连接时要经过三次握手,断开连接时要经过四次握手,中间传输数据时也要回复 ACK 包确认,多种机制保证了数据能够正确到达,不会丢失或出错。 ????????UDP是非连接的传输协议,没有建立连接和断开连接的过程,它只是简单地把数据丢到网络中,也不需要ACK包确认。UDP只有创建套接字的过程和数据交换的过程。 ????????TCP 的速度无法超越 UDP,但在收发某些类型的数据时有可能接近 UDP。例如,每次交换的数据量越大,TCP 的传输速率就越接近于 UDP。 |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/26 23:26:27- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |