本课讲解《白话C++》之练武的内容,看看《白话C++》为大家准备了哪些武器?
第10章 STL和boost
我们要学习的C++的第一类武器来自C++的标准库STL和准标准库boost。这两个库都比较大,特别是boost库包含了160多个子库。《白话C++》针对初学者做了一些选择。
“流 / stream”
我们上来就是三大套武器库。首先是“流”,这是一套传统工具,我们从写“Hello world”的时候就已经在用它了。这么讲吧,只要你一使出“流”这套武器,人家就知道你来自C++门派。
之前我们学习流的重点是使用,但是到了这个时候,我们要学习如何自定义流,如何实现自己定制的数据结构的输入、输出流的支持。我们还将从零开始,完整地实现一个充满C++风味的日志流。
小工具,如:随机数
接下来是一些比较小的,可以随身携带的武器。比如来自C++新标准库的随机数生成工具。哪一天我们要写一个电商程序的后台,然后想搞一些抽奖活动,就可以用到这里所学到的技术,来实现更公平(更随机)的随机数。
字符串工具集
最后的重点是在字符串身上的一组工具。字符串很普通但是也很常用。只是C++标准库所提供的字符串类不那么称手;所以我们很有必要学习boost特意为字符串提供的工具;不然的话我们行走江湖很容易阴沟里翻船。
智能指针
接下来就是“大杀器”了:智能指针。传统的C++内存管理很复杂,很容易让程序的内存管理、 内存使用变成一出“宫斗剧”。为了降低内存管理的难度,C++11(新标)无情的废弃了旧的智能指针 auto_ptr;但是我们还是会特意去了解它,不是为了使用,而是为了从错误中学习。
我们的学习重点当然是新进标准库的三大智能指针。除此之外,还会学习附加赠送来自boost的库的两个智能指针。
学好这一章,“妈妈再也不用担心我们写C++程序的内存管理了“。
迭代器
迭代器也是我们避免直接使用的一种方法。不过,迭代器更主要的用处是容器的“导游”。请大家记住这个比喻:
容器是“公园”,数据是“公园”里头的“景点”,而迭代器则是带领我们如何游历“公园”的“导游”。
容器和算法
容器是“公园”,公园有不同的内部结构,所以容器在C++中也是数据结构的一种纯粹的表现。在大学的课程里,数据结构和算法,它们是姊妹篇,通常存在紧密的绑定。第10章除了会复习老朋友:vector、list 等容器之外,还会学习:队列、优先队列、集合、映射、哈希表……等等数据容器;以及可以用在他们身上的一些常用算法,包括但不限于:遍历、逆转、排序、查找……等等。
C++是主流语言中提供数据结构最齐全、算法最丰富的语言(没有之一),尽管如此,仍然会有我们需要自己去实现一些算法的时候,为了更好的写算法,特别是更好的实现算法与数据结构的紧密结合,我们还需要学习 “函数绑定” 和 “lambda” 等C++语法知识。
时间、文件系统
第10章最后学习的是时间和文件系统。它们入选的理由也非常的充足。在现实生活中,办什么事情离得开时间这个因素呢?而在一台计算机上,办什么事情离得开文件系统的支持呢?
第11章 GUI
之前的课堂我们说过:“GUI编程是程序员的一场爱情”,所以我们在这里多闲聊几句吧:爱情是一件很特殊的事情,它不像解答数学题那样有标准答案;它需要我们去捉摸、去理解对方的心理。这就非常像GUI编程了:GUI是直接面向用户的,并且同一个功能的实现,往往没有特定的标准答案。我们需要去捉摸、理解用户的心理,才能把GUI程序写好。
传统GUI编程,比如桌面应用程序是C++的强项。学习GUI编程有什么好处:
你在这里学到了GUI编程概念、知识,哪怕你换编程语言、换操作系统、换架构、换硬件、换成BS结构写网页、换成开发智能手机上的APP、换成在浏览器上使用 Canvas 绘图、它们仍将为你提供有效的认知经验。事实上更多的情况是:你退居后端,不直接写用户界面,但是你今天在这里所学到的知识能让你更理解前端,从而设计出更好的面向前端的接口。
在练习和实践项目上,我们会先简单的体验Windows的原生GUI编程,然后我们会以wxWidgets为教学库,开始学习跨平台的GUI编程。
会有许多的练习例子,其中,具有实际应用价值的例子是这三个:屏幕保护、记事板和小画板。小画板有10个进化版本40个学习步骤。
其中的 Undo / Redo 的设计和实现,不管是在国内还是国外,通常都是大学里头计算机专业课程的必修课。
下面展现的就前面我们提到的,我们要在GUI课程中学到的部分相关概念和知识点:
- 布局 (layout)
- 资源 (Resource)
- 颜色组成 (RGB)
- 模型、视图、控制器 (MVC)
- UNDO / REDO
- 画笔(Pen)、画刷(Brush),绘图上下文(DC)
- 消息(Message)、消息队列(Message Queue)
- 事件(Event)
- 图层 (Layer)
- 主菜单(Main Menu)、弹出菜单(Popup Menu)
- 分辨率、解析率
- 剪贴板(Clipboard)
- 文档、视图模型
- 滚动区域
- ……
第12章 并发
并发课程上来就是一段代码:
#include <iostream>
#include <thread>
int main()
{
std::cout << "我家电脑CPU共计:"
<< std::thread:hardware_concurrency() << "核" << std::endl;
}
虽然看起来也很简单,并且这段代码完全不存在并发;但是请把它当成是学习并发编程的 “Hello world” 一样看待。
书里说:如果这段代码在你的电脑上输出的结果是:1,那你就可以把自家电脑砸了。
除了一开始的一些基础知识,并发的主要概念就是:异步、线程、承诺、同步以及并发编程与图形用户界面相结合时,通常需要注意的一些知识点等等。
这里还有一句话:
“并发是网络的基础”
我们学并发的时候,主要是学习如何在一台电脑上,甚至就是在一个程序里头,利用多颗或多核CPU同时干更多的活;而网络编程,不难理解,就是可以在多台计算机上同时干活了。所以网络的本质也是并发,只不过并发之间的交互,从多个线程之间变成多台机器、多个进程之间的交互。
第13章 网络
2023年的3月20号,有一条不起眼的科技新闻:有一个网络工具叫 CURL,它25周岁了。
CURL网络库的用户数(安装量)已经超过100亿。我保证你也一定在直接或间接的使用它。并且它也正好是我在3年前规划《白话C++》时,给用户准备的第一个要学习的网络库。
我们重点学习 libCURL 实现两个C++的实战网络项目:
- HTTP在线抓图
- FTP的客户端
libCURL 基本只用作网络编程中的客户端。我们学习的第二个网络库叫ASIO,它来自 boost (未来很有可能进入标准库)。它既可以用来写客户端也可以用来写服务端。
请大家注意一下它的名字 asio。当中的 “as" 是异步 (asynchronous) 的意思,而 io 是输入输出。asio 的核心重点就是异步。我们将涉及asio需学习到的知识点罗列在这里:
- 网络基础知识:TCP、UDP (以及基于 tcp 的 ftp、http、https);
- asio 核心 class 及对应核心概念讲解,对比了 libcurl 和 asio 在同样功能上实现差异;
- 实践1: echo 客户端与服务端(涉及通信报文的设计与读写);
- asio 出错处理;
- asio 同步编程;
- asio 并发处理 (包括结合C++11中的std::future);
- 实践2: TCP 代理服务器;
- 实践3: 聊天室;
- UDP 编程;
- GUI 界面 + 网络 : wxWidgetes 的网络功能;
- C++ WEB 编程
- ……
其中的“聊天室”项目,涉及到的GUI编程、多线程编程、网络编程。而网络编程这一块又包括服务端编程和客户端编程;并且这两者还采用了不同的网络库;客户端我们使用wxWidgets的自带的网络库,而服务端使用 asio。这个项目的复杂度,大抵上已经超出将来你工作时你的上司敢放手让你独立完成的第一个工作的复杂度。
网络编程是一件非常复杂的事情,所以,第13章大概也是插图最多的一章。下面是一些示例:
- 客户端并发是“不道德”的,因为它“贪得无厌”,而服务的并发却是劳模:
- TCP可以实现全双工,即数据上行与下行互不干扰(TCP代理的例子):
- 但是,在同一连接上的同一方向,并发处理却是危险的:
- asio的并发模型之一,一条流水线,多个工人并行干活:
- 聊天室项目截图:
- C++ WEB编程示例:
第14章 数据
在这一章,我们表面上是要学习 mysql 数据库,学习 redis 数据缓存,学习 JSON 的数据格式,但实际,这一章我们最大的收获是:理解“数据驱动”编程。
C++经常用于写服务端程序,此时它处于一个中间的位置,它所发挥的作用很像一个加工厂。这个加工厂所需要的原材料来自上游,比如从一个仓库中获取。原材料当然是一种“数据”,所以这个仓库在编程中就被称为“数据库”。当然根据不同的需要和不同的情况,这个仓库也可以理解为加工厂所需要的原材料的供应商,或者就是淘宝上的一些商家。不管用什么做比喻,都具备一个特点:从数据库获取数据是比较慢的。意思是:不管是从仓库、供应商、还是从淘宝上调货,中间至少都存在一个物流过程;而这个物流过程,它需要有比较大的时间成本。
接下来我们就假设:原材料配齐,工厂开始生产。这时候又有可能发现:原材料有剩余,那么,这过剩的原材料该怎么处理呢?可以丢掉,也可以送回仓库,但通常工厂会选择:先存放到某个就近的临时仓库里,等到下次有需要的时候,可优先从这个就近的小仓库获取(从页降低前面提一的物流成本)。这个“就近的小仓库”就叫做“数据缓存库”。除了过剩的原材料之外,加工成品(或半成品)有时候也需要就近存储。比如,假设我们生产蛋糕,那么蛋糕做好之后,不一定能马上送给买家,更不适合去送回仓库;最好的办法就是就近存储(放冷藏柜里)。我们要学习的数据缓存库叫 redis。
“蛋糕”显然不能一直放在冷藏柜里,我们总是要送给用户的。这时候,就需要对“蛋糕”做一些包装,然后请“快递”将它送至用户。
说完这整个过程就很容易理解《白话C++》在“数据”章节里需要教大家哪些知识了。首先需要学习数据库——这其实是学习任何编程语言都需要的共同知识。然后是C++如何访问 mysql 数据库,如何查询、处理或提交数据。第三第四个,自然是学习 redis 这个 缓存库,以及C++如何连接访问读写 redis。最后是“加工厂”和“用户”之间的事情:如何理解(解析)用户发过来的请求(比如订货需求),以及怎么将加工的结果数据做某种打包 (比如按JSON格式打包)后,发送给用户。
大家有没有发现:在这整个过程中,我们一切都是在围绕着数据打转,一切也因数据而起,甚至你可以认为:用户之所以想购买我们的商品,也是源于某种数据,即:用户脑袋里的某个念头。
第15章 乐趣
在这一章我们重点写了三个项目:“桌面玫瑰”、“俄罗斯方块”以及“宝岛保卫战”。前两者基于wxWidgets实现,后者基于SDL。
肯定有不少同学喜欢玩游戏,但是请注意,第15章所说的乐趣,不是指玩游戏的乐趣,而是指写游戏的乐趣,即:创造的乐趣。那是一种我们亲自设计,然后亲手实现的那种乐趣。
以“宝岛保卫战”为例,我们都设计了什么?基于“游戏不够文本来凑”的“原则”,我们的小游戏的背景还是挺讲究恢宏大气的:
大明朝,外星人入侵地球,幸得武林盟主张三丰组织地球人抵抗,击退大部分外星人。但外星人留了一手,在某宝岛海底深处埋下一核心能源,并留下一小部分外星人守卫,以待后续再次入侵时,实现里应外合。未料时间一长,留守海底的外星人,被美丽的地球感化,化身鲸鱼帮助守护地球。又未料某岛国因核辐射,全岛居民变异为鸭子,竟以鸭屎为武器,发起对宝岛的攻击。外星人为防止核心能量出现异常,只好派出一艘UFO和大量飞机,发起对地球的攻击(包括鸭子)。场面错综复杂……谁胜谁负?是敌是友?蓝色星球能否延续数十亿年的文明?历史,选择了你!
第16章 下一步
没有终点。这是最后一章,主要是以《白话C++》共计16章(包括本章)为知识点,告诉读者,在《白话C++》练功与练武全16章之后,应该如何继续后续的学习。