Skip to content

Commit 7b8cc41

Browse files
committed
Updated to Chapter 8, Section 1
1 parent 754ddbc commit 7b8cc41

File tree

17 files changed

+341
-150
lines changed

17 files changed

+341
-150
lines changed

Structure.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@
504504

505505
重载一些语法糖,让`vector`的操作更简单。边写边讲。
506506

507-
- 重载`<<`运算符用于`push_back``>>`运算符用于`push_front`
507+
- 重载`<<`运算符用于`push_back`
508508
- 重载后缀`--`运算符用于`pop_back`,重载前缀`--`运算符用于`pop_front`
509509
- 重载单目`*`运算符用于返回`size`。略微涉及一点`auto``decltype`的使用。
510510
- 重载`<`运算符,用于字典序比较。

generalized_parts/01_welcome_to_cpp/05_sizeof_and_memory.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
\section{\texttt{sizeof} 与内存空间}
1+
\section{\texttt{sizeof}与内存空间}
22
我们在之前总是反复提及,整型与整型之间是不同的,浮点型与浮点型之间也是不同的。对于整型来说,有符号与无符号是一个区别,而``容量''是另一个区别。如何理解这里的``容量''呢?这就要我们深入到``内存''中去,一探究竟。\par
33
\subsection*{什么是内存?}
44
张三正在用电脑打单机游戏,这时突然停电了。好不容易等到来电,张三心急如焚地打开电脑,刚准备继续玩,突然发现自己忘了存档,当前游戏进度还是昨天的进度。这让他非常不爽。\par

generalized_parts/06_custom_types_and_their_use/01_enum.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
\section{枚举常量}
1+
\section{枚举常量\texttt{enum}}
22
定义一个枚举常量的基本格式如下:\footnote{本节只介绍无作用域枚举,关于有作用域枚举,请见精讲篇。}
33
\begin{lstlisting}
44
enum <枚举名> {<枚举项>=<整型常量表达式>, <枚举项>=<整型常量表达式>, ...};

generalized_parts/06_custom_types_and_their_use/02_struct.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
\section{结构体}
1+
\section{结构体\texttt{struct}}
22
我们之前讲过的各数据类型,除了数组以外,都是只能表示单个数据的。比如说一个 \lstinline@double@ 数据,虽然它有8个字节,但是它的64个比特全都用来表示单个数据了。但是我们很容易想到,现实中的很多东西不是单纯用一个数据就能描述清楚的。比如我要描述一个长方体的信息,我需要三个数据:长、宽、高。这三个数据最好放在一起,作为一个整体存在,所以``定义三个变量''的思路就有点太原始了。\par
33
所以我们自然会想到定义数组。
44
\begin{lstlisting}

generalized_parts/06_custom_types_and_their_use/04_union.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
\section{联合体}
1+
\section{联合体\texttt{union}}
22
联合体初看上去很像结构体,它们的定义语法极其相似,但是它们是完全不同的事物。
33
\begin{lstlisting}
44
union ValType {

generalized_parts/06_custom_types_and_their_use/05_introduction_to_class.tex

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
\section{类初步}
1+
\section{\texttt{class}初步}
22
{\large ``一个设计良好的类能为用户提供简洁易用的接口\footnote{接口(Interface),在信息技术中指能将不同部件连接起来的媒介。通过接口,不同部件之可以进行信息交换。例如,笔记本电脑有USB接口,如果手机通过数据线连到这个接口上,那么笔记本电脑就可以和手机交换信息。},并将其内部结构隐藏起来,用户根本不必了解其内部结构。如果内部结构不应该被隐藏——例如,因为用户需要随意改变类中的任何数据成员——你可以把这种类认为是`普通的老式数据结构'。''\footnote{原文:A well-designed class presents a clean and simple interface to its users, hiding its representation and saving its users from having to know about that representation. If the representation shouldn't be hidden - say, because users should be able to change any data member any way they like - you can think of that class as `just a plain old data structure'.}}
33
\begin{flushright}——比雅尼·斯特劳斯特鲁普\end{flushright}\par
44
我们在第二节中所介绍的结构体更接近于C风格。它只能实现``把多个数据包装到一个对象中''的功能。而在使用时,我们可以任意地改变它的成员变量。这样做的好处是方便,简单,直接。如果我们要写一个结构体来管理单链表,我们完全可以这样写:
@@ -99,15 +99,15 @@ \subsection*{类的成员函数}
9999
str2.assign("Bjarne Stroustrup"); //由str2调用assign
100100
\end{lstlisting}
101101
\lstinline@str2@ 调用 \lstinline@assign@ 的时候,程序会把 \lstinline@"Bjarne Stroustrup"@ 作为 \lstinline@const char*@ 数据传给 \lstinline@assign@ 函数\footnote{实际被传递的还有 \lstinline@&str2@,作为隐藏参数 \lstinline@this@ 传递。详见第八章。}。在函数调用期间,\lstinline@strncpy@ 会改变私有成员 \lstinline@_str@ 的内容,而 \lstinline@strlen@ 会计算 \lstinline@_str@ 的有效长度并以此改变 \lstinline@_length@。\par
102-
初学者,尤其是从C语言过渡到C++的学习者,往往会觉得 \lstinline@class@ 这种设置访问权限的写法实在是太麻烦了,还不如 \lstinline@struct@ 那样一切默认用 \lstinline@public@ 的方法好。
103-
\subsection*{\lstinline@vector@ 简介与示例}
102+
初学者,尤其是从C语言过渡到C++的学习者,往往会觉得 \lstinline@class@ 这种设置访问权限的写法实在是太麻烦了,还不如 \lstinline@struct@ 那样一切默认用 \lstinline@public@ 的方法好。这种想法对于小规模的工程来说还好,但是对于大规模的工程来说,如果没有成员函数加以封装,没有私有访问权限加以保护,那么我们很容易在复杂的工程中写很多冗余代码,或者是犯一些低级错误。这就像是我们用函数——我们当然可以不用函数,但用了函数能让我们的生活更轻松;或者像是我们用 \lstinline@const@——我们当然可以不用 \lstinline@const@,只要你能确保自己写代码时不犯误修改某个值的错误。但是我们还是会选择用它们,也会选择用 \lstinline@class@ 代替 \lstinline@struct@,道理也是一样的。等到读者有了更多的编码经验之后,想必也会体会到这一点。\par
103+
\subsection*{\texttt{vector}简介与示例}
104104
C++中有一个动态数组类模版 \lstinline@vector@,它定义在头文件 \lstinline@vector@ 中,是STL的一部分。我们暂时不讲STL,但可以以它为例,讲一下类的成员函数的应用。
105-
它是一个类模版,我们需要指定具体的类型,比如 \lstinline@int@ 或者 \lstinline@double@,从而让它变为一个类实例。为了避免过多的无关信息,我们直接这么写吧:
105+
它是一个类模版,我们需要指定具体的类型,比如 \lstinline@int@ 或者 \lstinline@double@,从而让它变为一个类实例。为了避免过多无关信息干扰读者的思路,我们直接这么写吧:
106106
\begin{lstlisting}
107107
#include <vector> //包含头文件vector
108108
using vecint = vector<int>; //vecint相当于vector<int>类的别名
109109
\end{lstlisting}
110-
接下来我们可以直接用 \lstinline@vecint@ 作为 \lstinline@vector<int>@ 类的别名,所以 \lstinline@vecint@ 就是一个类型——这样理解就好。\par
110+
接下来我们可以直接用 \lstinline@vecint@ 作为 \lstinline@vector<int>@ 类的别名,所以 \lstinline@vecint@ 就成了一个类型。这样理解就好。\par
111111
\lstinline@vecint@ 有一个成员函数 \lstinline@push_back@,它允许我们每次向这个动态数组中添加一个元素;还有一个成员函数 \lstinline@size@,它的返回值是当前数组的有效数字个数。
112112
\begin{lstlisting}
113113
vecint v; //定义一个v,这时它的有效数字个数为0
@@ -146,3 +146,4 @@ \subsection*{\lstinline@vector@ 简介与示例}
146146
\end{lstlisting}\par
147147
这些功能看上去让人眼花瞭乱,但它们的思路都不难想,我们有了一定的基础之后也可以自己写一个低配版的 \lstinline@vecint@ 出来。在后面的章节中我们会实操一些相关方面的内容,比如实现 \lstinline@vector@, \lstinline@valarray@, \lstinline@string@ 和 \lstinline@stack@ 等——看上去很吓人,但实际上没有那么难。当读者把这些代码的构建全部练过一遍之后,读者对C++的理解想必会更上一层楼。\par
148148
不过莫急,我们先插叙一章,来讲讲代码工程的相关知识。\par
149+
34

generalized_parts/07_projecting/04_coding_style.tex

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ \subsubsection*{代码排版}
2626
std::cout << arr[i].member;
2727
\end{lstlisting}
2828
注意这里的 \lstinline@std::cout@ 和 \lstinline@arr[i].member@ 之间没有空格,其实也可以有。我的理解是:这里不需要空格,因为它们是用来表示同一个事物的,所以不需要用空格来区分开。读者当然也可以有自己的理解,并逐渐形成自己的风格,只要它易读就好了。\par
29-
对于缩进和换行来说,不同代码风格的习惯更是迵异——不过大体原则还是相似的,无非是在花括号是否换行、标签是否不缩进等细节上有出入。
30-
一般我们默认,在逻辑上有附属关系的语句之间最好加一层缩进。例如说 \lstinline@if@ 语句的作用域内,就要加一层缩进。
29+
对于缩进和换行来说,不同代码风格的习惯更是迵异——不过大体原则还是相似的,无非是在花括号是否换行、标签是否不缩进等细节上有出入。\par
30+
斯特劳斯特鲁普在自己的文章\footnote{\href{https://www.stroustrup.com/Programming/PPP-style.pdf}{\textit{PPP Style Guide} - Bjrane Stroustrup}}中简单介绍了一种C++编码风格,它是对K\&R风格\footnote{K\&R风格(Kernighan \& Ritchie Style, K\&R style)是一种常见于C/C++等花括号编程语言的风格,其核心特点在于:首尾花括号与引出花括号的语句保持相同缩进,而花括号内的语句增加一层缩进。}的变体。本书也推荐读者学习和使用这种``斯特劳斯特鲁普变体''\footnote{至于其它的常见编码风格,\href{https://en.wikipedia.org/wiki/Indentation_style\#Brace_placement_in_compound_statements}{Brace placement in compound statements - Wikipedia} 列表中有所介绍。读者也可以挑选一种合自己心意的来使用。}。接下来对它作简要介绍;如果读者希望了解更多,可以去阅读他的文章。\par
31+
一般我们会对逻辑上有附属关系的语句加一层缩进。例如说 \lstinline@if@ 语句的作用域内,就要加一层缩进。
3132
\begin{lstlisting}
3233
if (a > 0)
3334
std::cout << "Positive";
@@ -36,7 +37,7 @@ \subsubsection*{代码排版}
3637
else
3738
std::cout << "Zero";
3839
\end{lstlisting}
39-
其它诸如 \lstinline@for@, \lstinline@while@, \lstinline@switch@ 等结构,以及函数定义、类定义等也是如此。至于花括号在什么位置,它要不要独占一行,又怎么缩进,那就是一个人一个风格了\footnote{\href{https://en.wikipedia.org/wiki/Indentation_style\#Brace_placement_in_compound_statements}{Brace placement in compound statements - Wikipedia} 列表中为我们展示了几种常见的花括号风格。读者可以挑选一种合自己口味的来用。}。\par
40+
其它诸如 \lstinline@for@, \lstinline@while@, \lstinline@switch@ 等结构,以及函数定义、类定义等也是如此。\par
4041
再比如,在初始化数组的时候,假如初始化内容非常冗长,我们也可以换行加适当缩进。
4142
\begin{lstlisting}
4243
struct Data {
@@ -62,7 +63,8 @@ \subsubsection*{代码排版}
6263
//适当换行+缩进
6364
if (ch > 'a' && ch < 'z'
6465
|| ch > 'A' && ch < 'Z'
65-
|| ch > '0' && ch < '9'){
66+
|| ch > '0' && ch < '9'
67+
){
6668
//...
6769
}
6870
\end{lstlisting}

generalized_parts/08_a_step_forward_in_classes_and_functions.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
\chapter{类与函数进阶}
22
到第七章结束,读者应当已经掌握了C++语言的必要知识,并具备了独立搭建简单C++工程的能力。因此从本章开始,我也会略微转换讲解风格,不再用长篇累牍的知识点,大水漫灌。我将带领读者,从一些简单的例子开始练习,进而完成一个类,一个类模版,或是一系列函数,从而实现一些功能。\par
33
我的目标是,在本章的结尾带领读者写出一个简化版的 \lstinline@string@ 类。C++的 \lstinline@string@ 库中已经有这个类,按理说不需要我们实现。但是,``会用''``会写''还是不一样的!在用的时候,我们对很多陷阱一无所知,对很多问题浑然不觉——这恰恰是封装良好的优点,我们使用某个功能时无需在这些杂碎问题上浪费不必要的时间——一旦自己从头开始搭建,这些问题就会纷纷暴露出来。\par
4-
只有用过了知识,我们才能掌握;只有暴露了问题,我们才能进步。任何一门编程语言都是如此,C++更不例外\par
4+
只有用过了知识,我们才能掌握;只有暴露了问题,我们才能进步。任何一门编程语言都是如此,C++也不例外\par
55
\import{08_a_step_forward_in_classes_and_functions/}{01_operator_overloading.tex}
66
\import{08_a_step_forward_in_classes_and_functions/}{02_friend.tex}
77
\import{08_a_step_forward_in_classes_and_functions/}{03_constructor_and_destructor.tex}

0 commit comments

Comments
 (0)