C++ 编程思想(第一卷)阅读总结

最近工作闲翻阅了之前买f《C++编程思想》这里贴上我认为对我最有帮助的部分,一来留给自己复习看,另一方面也和小伙伴们分享下:

预备知识―程序的内存分配 
一个由c/C++编译的程序占用的内存分为以下几个部分 
1、栈区(stack)―   由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 
2、堆区(heap) ―   一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 
3、全局区(静态区)(static)―,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 
4、文字常量区  ―常量字符串就是放在这里的。 程序结束后由系统释放 
5、程序代码区―存放函数体的二进制代码。

1 OPP相关

1.1、每个对象都有一个类型,OOP中class 和type是同义词,在面向对象的程序设计中,我们所做的工作实际上就是创造新的数据类型,程序员定义class 是为了与具体问题相适应,而不是被迫适用已存在的数据类型。

1.2、当用<>来指定文件时,预处理器以特定的方式来寻找文件,一般是环境中或者编译器命令指定的某种寻找路径;当采用""指定文件时,通常是从当前目录开始寻找,如果文件没有找到则按<>方式进行寻找。

2 C++总的C

2.1、整数类型范围从小到大为:short int->int->long int。

         浮点类型范围从小到大为:float->double->long double;

         unsigned 数不保存符号,因此有一个多余的位可用,所以它能存储比signed数大两倍整数

2.2、main()的内部和外部定义的变量存放在不同的区域;数据和函数也存在不同区域

2.3、C++编程的一般原则是在定义时进行初始化,const 变量必须有初始值

2.4、enum可以提高程序清晰度,采用union可以节省内存,所有union 变量地址都是一样的

2.5、 采用预处理器来完成代码调试功能,具体实现如下:

#define NDEBUG 
//......
#ifdef NDEBUG
/* debugging code here*/
......
#endif
2.6、C++允许将任何类型的指针赋给void* ,但是不允许将void* z指针赋值给其他任何类型的指针。

2.7、同文件是我们和库用户之间的合约,合约描述了库中的数据结构,为函数调用规定了参数和返回值,头文件中只限于申明,为了避免头文件的内容的多次申明,我们可以采用如下方式避免:

#ifndef HEADER_FLAG
#define HEADER_FLAG
//Type declaration here
.....
#endif
同样为了避免命名空间的错乱,头文件中绝不会看到using

2.8、如果程序员想允许显式让不属于当前结果的一个成员函数访问当前结构的对象时,可以借助friend 修饰符,friend 必须在一个结构内部声明

3 、C++特色:

3.1、class与struct 的区别在于class的成员默认是private,而struct的成员默认是public;

3.2、C++的安全性体现在初始化和清除两个方面,用构造函数确保初始化,用析构函数确保清除

3.3、C++中宏被内联函数(inline function)代替,这样既保证了高效性(成员函数和预处理器宏一样高效)也保证了安全性(当调用内联函数时,编译器首先确保调用正确,即所有的参数类型都满足,宏定义在预处理中,不能进行检查)。

任何在类中定义的函数都自动的成为内联函数;

使用内联函数的目的是减少函数调用的开心,但是如果函数交大,由于需要在调用函数的每一处重复赋值代码,这样会使得代码膨胀,因此小函数作为内联函数比较理想

3.4、static使得变量存于静态数据区中,而不是堆栈中。全局静态对象的构造函数在main()之前调用,并且在退出main()后调用析构函数;

3.5、 关键字namespace如何class、struct、enum和union一样把它们的成员的名字放到不同的空间去,但namespace与class 、struct、union和enum有着明显的区别:

        (1)namespace只能在全局范围内定义,但他们之间可以相互嵌套;

        (2)namespace定义的结尾不必跟着分号;

(3)一个namespace可以在多个头文件中用一个标识符来定义;

(4)不能像class一样去创建一个名字的实例;

(5)namespace可以用另一个名字作为他的别名;

3.6、 & 在C++表示引用,引用可以理解为一个奇特的指针,这个指针的优点是不必怀疑它是否初始化,引用的使用规则如下:

(1)应用创建是必须初始化;

(2)一个引用指向一个对象后不可转变为另一个对象的引用;

(3)不能NULL的引用

最经常看见引用的地方是函数参数和返回值中,当引用被用作函数参数是,在函数内任何对引用对象的修改将在函数外参数发生变化,当然也可传递指针来做相同的事情,但引用具有更清晰的语法。

3.7、拷贝构造函数(copy-constructor)是一种特殊的构造函数,需要引用来实现从现有的相同类型的对象中产生新的对象。编译器使用拷贝构造函数通过值传递的方式在函数中传递和返回对象

3.8、使用delete void * 可能会出错,在删除之前必须把它转为适当的类型,否则将会丢失内存;

3.9、C++确保在进入新类的构造函数体之前调用酥油的其他的构造函数,这样所有子对象的成员函数所做的任何调用总是转到这个被初始化的对象中,

MyType::MyType(int i):Bar(i){///....}

4 C++ 中的多态

4.1、多态永远发生在派生类中与基类之间,C++通过virtual函数和晚绑定(late binding)实现;

如果一个函数在基类中被申明为virtual ,那么所有的派生类中它都是virtual,可以对基类中的虚函数进行重写;

在每个带有虚函数的类中,编译器秘密放置了一个指针(vpointer)指向该对象的VTABLE(编译器对每个包含虚函数的类创建一个表:VTABLE)


编译器从Instrument指针开始,该指针指向该对象的起始地址,对于所有的Instrument或派生对象,他们的vptr都存在相同的位置(常常在对象的开头),所以编译器能够取出该对象的vptr,vptr指向vtable的起始地址,所有的vtable都有相同的顺序,如图。play()第一个,what()第2个;

5、C++模板(template)

5.1、template告诉编译器,随后定义将错做一个或者多个未指明的类型,当这个模板产生实际类代码时,必须指定这些类型使得编译器可以替换他们。



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++编程思想,目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 多态性 2 1.1.4 操作概念:OOP程序像什么 3 1.2 为什么C++会成功 3 1.2.1 较好的C 3 1.2.2 采用渐进的学习方式 4 1.2.3 运行效率 4 1.2.4 系统更容易表达和理解 4 1.2.5 “库”使你事半功倍 4 1.2.6 错误处理 5 1.2.7 大程序设计 5 1.3 方法学介绍 5 1.3.1 复杂性 5 1.3.2 内部原则 6 1.3.3 外部原则 7 1.3.4 对象设计的五个阶段 9 1.3.5 方法承诺什么 10 1.3.6 方法应当提供什么 10 1.4 起草:最小的方法 12 1.4.1 前提 13 1.4.2 高概念 14 1.4.3 论述(treatment) 14 1.4.4 结构化 14 1.4.5 开发 16 1.4.6 重写 17 1.4.7 逻辑 17 1.5 其他方法 17 1.5.1 Booch 18 1.5.2 责任驱动的设计(RDD) 19 1.5.3 对象建模技术(OMT) 19 1.6 为向OOP转变而采取的策略 19 1.6.1 逐步进入OOP 19 1.6.2 管理障碍 20 1.7 小结 21 第2章 数据抽象 22 2.1 声明与定义 22 2.2 一个袖珍C库 23 2.3 放在一起:项目创建工具 29 2.4 什么是非正常 29 2.5 基本对象 30 2.6 什么是对象 34 2.7 抽象数据类型 35 2.8 对象细节 35 2.9 头文件形式 36 2.10 嵌套结构 37 2.11 小结 41 2.12 练习 41 第3章 隐藏实现 42 3.1 设置限制 42 3.2 C++的存取控制 42 3.3 友元 44 3.3.1 嵌套友元 45 3.3.2 它是纯的吗 48 3.4 对象布局 48 3.5 类 48 3.5.1 用存取控制来修改stash 50 3.5.2 用存取控制来修改stack 51 3.6 句柄类(handle classes) 51 3.6.1 可见的实现部分 51 3.6.2 减少重复编译 52 3.7 小结 54 3.8 练习 54 第4章 初始化与清除 55 4.1 用构造函数确保初始化 55 4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 68 4.9 练习 68 第5章 函数重载与缺省参数 69 5.1 范围分解 69 5.1.1 用返回值重载 70 5.1.2 安全类型连接 70 5.2 重载的例子 71 5.3 缺省参数 74 5.4 小结 81 5.5 练习 82 第6章 输入输出流介绍 83 6.1 为什么要用输入输出流 83 6.2 解决输入输出流问题 86 6.2.1 预先了解操作符重载 86 6.2.2 插入符与提取符 87 6.2.3 通常用法 88 6.2.4 面向行的输入 90 6.3 文件输入输出流 91 6.4 输入输出流缓冲 93 6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 6.10 输入输出流实例 111 6.10.1 代码生成 111 6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向const的指针 127 7.2.2 const指针 127 7.2.3 赋值和类型检查 128 7.3 函数参数和返回值 128 7.3.1 传递const值 128 7.3.2 返回const值 129 7.3.3 传递和返回地址 131 7.4 类 133 7.4.1 类里的const和enum 133 7.4.2 编译期间类里的常量 134 7.4.3 const对象和成员函数 136 7.4.4 只读存储能力 139 7.5 可变的(volatile) 140 7.6 小结 141 7.7 练习 141 第8章 内联函数 142 8.1 预处理器的缺陷 142 8.2 内联函数 144 8.2.1 类内部的内联函数 145 8.2.2 存取函数 146 8.3 内联函数和编译器 150 8.3.1 局限性 150 8.3.2 赋值顺序 150 8.3.3 在构造函数和析构函数里隐藏行为 151 8.4 减少混乱 152 8.5 预处理器的特点 153 8.6 改进的错误检查 154 8.7 小结 155 8.8 练习 155 第9章 命名控制 157 9.1 来自C语言中的静态成员 157 9.1.1 函数内部的静态变量 157 9.1.2 控制连接 160 9.1.3 其他的存储类型指定符 161 9.2 名字空间 161 9.2.1 产生一个名字空间 162 9.2.2 使用名字空间 163 9.3 C++中的静态成员 166 9.3.1 定义静态数据成员的存储 166 9.3.2 嵌套类和局部类 168 9.3.3 静态成员函数 169 9.4 静态初始化的依赖因素 171 9.5 转换连接指定 174 9.6 小结 174 9.7 练习 174 第10章 引用和拷贝构造函数 176 10.1 C++中的指针 176 10.2 C++中的引用 176 10.2.1 函数中的引用 177 10.2.2 参数传递准则 178 10.3 拷贝构造函数 179 10.3.1 传值方式传递和返回 179 10.3.2 拷贝构造函数 182 10.3.3 缺省拷贝构造函数 187 10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 多态性 2 1.1.4 操作概念:OOP程序像什么 3 1.2 为什么C++会成功 3 1.2.1 较好的C 3 1.2.2 采用渐进的学习方式 4 1.2.3 运行效率 4 1.2.4 系统更容易表达和理解 4 1.2.5 “库”使你事半功倍 4 1.2.6 错误处理 5 1.2.7 大程序设计 5 1.3 方法学介绍 5 1.3.1 复杂性 5 1.3.2 内部原则 6 1.3.3 外部原则 7 1.3.4 对象设计的五个阶段 9 1.3.5 方法承诺什么 10 1.3.6 方法应当提供什么 10 1.4 起草:最小的方法 12 1.4.1 前提 13 1.4.2 高概念 14 1.4.3 论述(treatment) 14 1.4.4 结构化 14 1.4.5 开发 16 1.4.6 重写 17 1.4.7 逻辑 17 1.5 其他方法 17 1.5.1 Booch 18 1.5.2 责任驱动的设计(RDD) 19 1.5.3 对象建模技术(OMT) 19 1.6 为向OOP转变而采取的策略 19 1.6.1 逐步进入OOP 19 1.6.2 管理障碍 20 1.7 小结 21 第2章 数据抽象 22 2.1 声明与定义 22 2.2 一个袖珍C库 23 2.3 放在一起:项目创建工具 29 2.4 什么是非正常 29 2.5 基本对象 30 2.6 什么是对象 34 2.7 抽象数据类型 35 2.8 对象细节 35 2.9 头文件形式 36 2.10 嵌套结构 37 2.11 小结 41 2.12 练习 41 第3章 隐藏实现 42 3.1 设置限制 42 3.2 C++的存取控制 42 3.3 友元 44 3.3.1 嵌套友元 45 3.3.2 它是纯的吗 48 3.4 对象布局 48 3.5 类 48 3.5.1 用存取控制来修改stash 50 3.5.2 用存取控制来修改stack 51 3.6 句柄类(handle classes) 51 3.6.1 可见的实现部分 51 3.6.2 减少重复编译 52 3.7 小结 54 3.8 练习 54 第4章 初始化与清除 55 4.1 用构造函数确保初始化 55 4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 68 4.9 练习 68 第5章 函数重载与缺省参数 69 5.1 范围分解 69 5.1.1 用返回值重载 70 5.1.2 安全类型连接 70 5.2 重载的例子 71 5.3 缺省参数 74 5.4 小结 81 5.5 练习 82 第6章 输入输出流介绍 83 6.1 为什么要用输入输出流 83 6.2 解决输入输出流问题 86 6.2.1 预先了解操作符重载 86 6.2.2 插入符与提取符 87 6.2.3 通常用法 88 6.2.4 面向行的输入 90 6.3 文件输入输出流 91 6.4 输入输出流缓冲 93 6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 6.10 输入输出流实例 111 6.10.1 代码生成 111 6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向const的指针 127 7.2.2 const指针 127 7.2.3 赋值和类型检查 128 7.3 函数参数和返回值 128 7.3.1 传递const值 128 7.3.2 返回const值 129 7.3.3 传递和返回地址 131 7.4 类 133 7.4.1 类里的const和enum 133 7.4.2 编译期间类里的常量 134 7.4.3 const对象和成员函数 136 7.4.4 只读存储能力 139 7.5 可变的(volatile) 140 7.6 小结 141 7.7 练习 141 第8章 内联函数 142 8.1 预处理器的缺陷 142 8.2 内联函数 144 8.2.1 类内部的内联函数 145 8.2.2 存取函数 146 8.3 内联函数和编译器 150 8.3.1 局限性 150 8.3.2 赋值顺序 150 8.3.3 在构造函数和析构函数里隐藏行为 151 8.4 减少混乱 152 8.5 预处理器的特点 153 8.6 改进的错误检查 154 8.7 小结 155 8.8 练习 155 第9章 命名控制 157 9.1 来自C语言中的静态成员 157 9.1.1 函数内部的静态变量 157 9.1.2 控制连接 160 9.1.3 其他的存储类型指定符 161 9.2 名字空间 161 9.2.1 产生一个名字空间 162 9.2.2 使用名字空间 163 9.3 C++中的静态成员 166 9.3.1 定义静态数据成员的存储 166 9.3.2 嵌套类和局部类 168 9.3.3 静态成员函数 169 9.4 静态初始化的依赖因素 171 9.5 转换连接指定 174 9.6 小结 174 9.7 练习 174 第10章 引用和拷贝构造函数 176 10.1 C++中的指针 176 10.2 C++中的引用 176 10.2.1 函数中的引用 177 10.2.2 参数传递准则 178 10.3 拷贝构造函数 179 10.3.1 传值方式传递和返回 179 10.3.2 拷贝构造函数 182 10.3.3 缺省拷贝构造函数 187 10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值