Skip to content

Commit 24045db

Browse files
committed
Updated to Chapter 9, Section 3
1 parent ab2dfe8 commit 24045db

File tree

16 files changed

+473
-89
lines changed

16 files changed

+473
-89
lines changed

Structure.md

+7-13
Original file line numberDiff line numberDiff line change
@@ -649,14 +649,8 @@
649649

650650
(前述的`valarri::Arr`正是一个绝佳的例子)
651651

652-
#### 基本语法
653-
654-
同上的部分同上,讲下区别就行。
655-
656652
#### 构造与初始化
657653

658-
同上的部分同上。重点在于它和公开继承不同的地方。
659-
660654
#### 编程示例:适配`vector<int>``stack`
661655

662656
这里通过私有继承`vector<int>`的方式写一个简单的`stack`,实现一些最基本的功能。
@@ -677,10 +671,12 @@
677671

678672
这一节很重要。
679673

680-
基类指针可以指向派生类对象;基类引用可以引向派生类对象。它们能操作哪些成员
674+
向上继承和向下继承如何实现
681675

682676
动态类型转换 `dynamic_cast` 又是怎么回事。
683677

678+
基类指针可以指向派生类对象;基类引用可以引向派生类对象。它们能操作哪些成员。
679+
684680
### 虚函数`virtual`
685681

686682
#### 编程示例:不同动物的叫声
@@ -879,11 +875,7 @@
879875

880876
`const`常量不是任何类型,它可以用于组合各种类型,以及组合成员函数(相当于组合了`*this`)。
881877

882-
#### `multable`限定符
883-
884-
即便对象是常量,它的`multable`成员也是可以修改的。
885-
886-
> `volatile`不讲,我自己还没搞懂呢……
878+
> `volatile`不讲 <!-- 我自己还没搞懂呢…… -->
887879
888880
### 数据的定义和初始化
889881

@@ -1023,7 +1015,7 @@ Placement new。主要是介绍下布置分配的语法和注意事项(结束
10231015

10241016
通过几个算法,尝试使用函数对象。
10251017

1026-
## 类与结构
1018+
##
10271019

10281020
### 访问权限
10291021

@@ -1166,3 +1158,5 @@ Placement new。主要是介绍下布置分配的语法和注意事项(结束
11661158
### 进制转换
11671159

11681160
### 布尔代数基础
1161+
1162+
### 位运算

code_in_book/8.3-8.5/Header.h renamed to code_in_book/8.3-8.4/Header.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class string { //class的默认成员访问权限是private,所以private可
99
class Arr {
1010
char *_p;
1111
public:
12-
Arr(char* ptr = {nullptr}) : _p {ptr} {} //Arr的构造函数
12+
Arr(char *ptr = {nullptr}) : _p {ptr} {} //Arr的构造函数
1313
char*& p() { return _p; } //当arr不是常量时调用
1414
const char* p()const { return _p; } //当arr是常量时调用
1515
} _arr {new char[_cap]}; //象征指针的成员,默认用new char[_cap]初始化

code_in_book/9.1-9.2/Definition.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include "Header.h"
2+
stack::stack(const std::vector<int> &v) : std::vector<int>{v} {}
3+
//构造函数
4+
stack::stack(const stack &s) : std::vector<int>{s} {}
5+
//拷贝构造函数
6+
stack& stack::operator=(const stack &s) {
7+
if (this == &s) //防止自我赋值
8+
return *this;
9+
std::vector<int>::operator=(s);
10+
//调用std::vector<int>的赋值运算符,并借助隐式类型转换参数传递
11+
return *this;
12+
}
13+
void stack::push(const int &val) {
14+
push_back(val); //将调用std::vector<int>::push_back
15+
}
16+
void stack::pop() {
17+
pop_back(); //将调用std::vector<int>::pop_back
18+
}
19+
void stack::swap(stack &s) {
20+
std::vector<int>::swap(s);
21+
}
22+
bool stack::operator<(const stack &s)const {
23+
return *this < static_cast<std::vector<int>>(s);
24+
}
25+
bool stack::operator>(const stack &s)const {
26+
return s < *this;
27+
}
28+
bool stack::operator<=(const stack &s)const {
29+
return !(s < *this);
30+
}
31+
bool stack::operator>=(const stack& s)const {
32+
return !(*this < s);
33+
}
34+
bool stack::operator==(const stack &s)const {
35+
return !operator!=(s); //利用已经声明的stack::operator!=
36+
}
37+
bool stack::operator!=(const stack &s)const {
38+
return *this < s || s < *this; //比较运算符的优先级高于逻辑或运算符
39+
}

code_in_book/9.1-9.2/Header.h

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
#include <vector>
3+
class stack : std::vector<int> {
4+
public:
5+
explicit stack() {} //什么也不做
6+
explicit stack(const std::vector<int>&); //接收一个std::vector<int>对象
7+
stack(const stack&); //拷贝构造函数
8+
//用默认析构函数足矣,无需自行定义
9+
stack& operator=(const stack&); //赋值运算符
10+
int& top() { return back(); } //调用std::vector<int>的back函数
11+
const int& top()const { return back(); } //常成员函数版本
12+
bool empty()const { return size(); } //调用谁的size函数?
13+
std::size_t size()const { return std::vector<int>::size(); }
14+
//调用std::vector<int>的size()函数
15+
void push(const int&); //堆入数据
16+
void pop(); //移出数据
17+
void swap(stack&); //交换内容
18+
bool operator<(const stack&)const;
19+
bool operator>(const stack&)const;
20+
bool operator<=(const stack&)const;
21+
bool operator>=(const stack&)const;
22+
bool operator==(const stack&)const;
23+
bool operator!=(const stack&)const; //六个比较运算符
24+
};

generalized_parts/08_a_step_forward_in_classes_and_functions/07_exercise_string_class.tex

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ \subsection*{功能简介}
1010
\item 有的构造函数是在另一个字符串对象 \lstinline@other@ 中截取 \lstinline@pos@ 开始的 \lstinline@count@ 个字符。
1111
\item 有的构造函数是以一个 \lstinline@char*@ 字符串的内容为内容建立起来的。
1212
\item 有的构造函数是用一个列表来初始化的,我们在前面讲 \lstinline@valarri@ 时也介绍过。
13+
\item 还有各种拷贝构造函数/移动构造函数\footnote{泛讲篇不讲移动构造,详见精讲篇。}。
1314
\item ……
1415
\end{itemize}
1516
种种构造函数不一而足,我们当然也没有必要全部实现,拣一些常用的就行了。\par
@@ -560,5 +561,5 @@ \subsection*{实现}
560561
}
561562
\end{lstlisting}\par
562563
\subsection*{完整代码}
563-
\lstinputlisting[caption=\texttt{Header.h}]{../code_in_book/8.3-8.5/Header.h}
564-
\lstinputlisting[caption=\texttt{Definition.cpp}]{../code_in_book/8.3-8.5/Definition.cpp}
564+
\lstinputlisting[caption=\texttt{Header.h}]{../code_in_book/8.3-8.4/Header.h}
565+
\lstinputlisting[caption=\texttt{Definition.cpp}]{../code_in_book/8.3-8.4/Definition.cpp}

generalized_parts/09_class_inheritance/01_the_concepts_of_inheritance.tex

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
\section{概念介绍}
1+
\section{基本概念}
22
以下三种关系是C++中常见的,读者务必搞清楚它们之间的区别,切勿混淆。\par
33
\subsection*{整体与部分(Has-a relationship)}
44
还记得我们在第六章讲述结构体时如何说吗?

generalized_parts/09_class_inheritance/02_public_inheritance_and_protected_members.tex

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ \subsection*{构造与初始化}
102102
void guide() { /*...*/ } //金毛独特的导盲本领
103103
};
104104
\end{lstlisting}\par
105-
在这里,我们把 \lstinline@Dog@ 类的构造函数定义成受保护成员。按前文所述,这些成员对派生类以外的外界都是不可见的,所以我们不能在外部使用这个函数来进行构造\footnote{其实这个类还有一个作为公有成员的默认拷贝构造函数,所以确实还存在这样的方法使我们能够在外部定义对象。}。换言之,我们这样就保证了:在外界中不能直接定义 \lstinline@Dog@ 类对象,只能定义它的派生类的对象\footnote{不过,从另一个意义上讲,派生类的对象也是基类的对象。}。\par
105+
在这里,我们把 \lstinline@Dog@ 类的构造函数定义成受保护成员。按前文所述,这些成员对派生类以外的外界都是不可见的,所以我们不能在外部使用这个函数来进行构造\footnote{其实这个类还有一个作为公有成员的默认拷贝构造函数和默认移动构造函数,所以确实还存在这样的方法使我们能够在外部定义对象。}。换言之,我们这样就保证了:在外界中不能直接定义 \lstinline@Dog@ 类对象,只能定义它的派生类的对象\footnote{不过,从另一个意义上讲,派生类的对象也是基类的对象。}。\par
106106
两个派生类 \lstinline@Husky@ 和 \lstinline@Retriever@ 对象的构造函数都是公有的,我们就可以在类外调用了。它们都接收三个参数,分别是 \lstinline@age@, \lstinline@weight@, \lstinline@ability@。所以我们可以这样定义对象:
107107
\begin{lstlisting}
108108
int main() {

0 commit comments

Comments
 (0)