C++程序设计与语言(特别版)

2017-01-10 19:20:55来源:cnblogs.com作者:导论 - Man了个Go人点击

前言

刚开始的时候只学习了一些简单的C++语法知识,当C++不再是一门学科需要考试的时候,就想重新把C++捡回来,希望从中学习到一点思想性的东西而不再是一些语法性的东西。
下面都是一些参考书目的摘抄或者自己的一点想法

第1章 致读者

1.6.1 给C程序员的建议

  1. 在C++里几乎不需要宏。用const或enum定义明显的常量,用inline避免函数调用的额外开销,用template去刻画一族函数或者类型,用namespace去避免名字冲突。
  2. 不要再你需要变量之前去声明它,以保证你立即对它进行初始化。声明可以出现在能出现语句的所有位置上,可以出现在for语句的初始化部分,也可以出现在条件中。个人觉得就是在动作发生时才去声明变量,一来提高代码可读性,二来避免污染或者未初始。
  3. 不用用malloc()。new运算符能将同样的事情做得更好。对于realloc(),请试一试vector()。
  4. 试着去避免void*、指针算术、联合和强制,除了在某些函数或类实现的深层之外。在大部分情况下,强制都是设计错误的指示器。如果必须使用某个显示的类型转换,请设法去用一个“新的强制”,设法写出一个描述你想做的事情的更精确的语句。
  5. 尽量少用数组和C风格的字符串。与传统的C风格相比,使用C++标准库string和vector常常可以简化程序的设计。
    如果要符合C的链接规则,一个C++函数就必须被声明为具有C链接的。

1.8 忠告

  1. 在编程序时,让程序的结构尽可能地直接反映这些思想:类--独立概念;对象--独立的实体;抽象类--共同的界面;基类--实现有些显著的共同东西;模板--一种对象的容器;模板函数--对某容器的一个算法;名字空间--类,模板等相互之间有逻辑联系。
  2. 在定义一个并不是实现某个像矩阵或复数这样的数学对象的类时,或者定义一个低层的类型如链接表的时候:不要使用全局数据,不要使用全局函数;不要使用公用数据成员;不要使用友元,除非避免前两个。

第2章 C++概览

2.3 过程式程序设计

  • 原始的程序设计范型是:
    确定你需要哪些过程;采用你能找到的最好的算法。

2.4 模块程序设计

  • 模块程序设计的范型变成了:
    确定你需要哪些模块;将程序分成一些模块,使数据隐藏于模块之中

2.4.1 分别编译

  • 分别编译的使用并不是语言要考虑的问题,而是关于如何最好地利用特定语言实现的优点的问题。分别编译就是把实现(.c),界面(.h),使用(.c)分离。感觉以前对.h的理解就是把界面和实现都放在了一起,把.h简单地理解成代码的分离和重用。
  • 最好的方式就是最大限度地模块化,通过语言特征去逻辑地表示模块化,而后通过能最有效地分别编译的一组文件,物理地利用这种模块化机制。

2.5.1 定义类型的模板namespace

  • 基于模板的程序设计趋向于以一个类型的所有数据为中心,在某个类型管理模板的控制之下工作。
  • 某个实现可以是预先分配几个堆栈,...这种做法常常不是最理想的。一个重要问题就是,这里给用户提供了一个“假类型”的表示,它可以因为表示类型不同而出现很大变化——而与此同时又应该将用户隔离于这一表示之外。
  • 更根本的问题是,通过模板实现的这种用户定义类型,他们说提供的对这种类型的访问,在行为上,并不像内部的类型。他们得到的支持也与内部类型不同,而且实际上更少一些。这里理解不是很透彻,是因为包装多个堆栈相比于单个堆栈提供了更少的方法,一些控制的方法无法在外部实现,灵活性低;还有就是容易造成歧义的原因吗?

2.5.2 用户定义类型class

  • 用户定义类型程序设计范型变成了:
    确定你需要哪些类型,为每个类型提供完整的一组操作。
  • 这里出现了friend,以前不理解友元的作用,这里专门去补了一下。1.首先类具有封装和信息隐藏的特性。只有类成员函数才能访问类的私有成员,但是多次调用某些成员函数会影响程序的运行效率;2.为了解决这个问题,友元是一种定义在类外部的普通函数或类,但它需要在类内进行说明,但是它可以访问类中的私有成员。3.它破坏了类的封装性和隐藏性,导致程序可维护性变差。(一提到可维护性就怕怕)

2.5.4 抽象类型

  • 在将Stack从一个用模板实现的“假类型”转变成为一个真正的类型的过程中,有一个性质被丢掉了:表示方式没有与用户界面分离,反而变成了使用Stack的程序片段里讲包含的一个部分。
  • 如果我们需要将堆栈的用户与堆栈表示的修改完全隔离开,这时需要放弃的就是真正的局部变量。virtual表示“可以在今后由这个类说派生的类里重新定义”。

2.5.5 虚函数

  • 怎样将虚函数的调用正确解析为函数的定义?一种常用的思想技术是让编译器在一个virtual函数的名字转换为指向这些函数的指针表的下标。这种表通常被称为“虚函数表”(vtbl)。每个带有虚函数的类都有标识着它的所有虚函数的vtbl。
  • 调用者需要知道的所有东西就是Stack的那个vtbl的位置,以及对各个虚函数应该使用的下标。其空间开销是带有虚函数的类的每个对象里包含一个指针,而每个这样的类需要一个vtbl。

2.6 面向对象的程序设计

  • 作者首先提了一个需要一直switch的例子,引出了继承的作用。
  • 现在程序设计范型是:
    确定你需要哪些类;为每个类提供完整的一组操作;利用继承去明确地表示共性。

2.7 通用型程序设计

  • 这个程序设计范型是:
    确定你需要哪些算法;将他们参数化,使他们能够对各种适当的类型和数据结构工作。

第3章 标准库概览

3.5.1 C风格的字符串

  • 一个C风格的字符串就是一个以0字符结束的字符数组。函数c_str()能够以C风格字符串的形式提取出string的值。

3.7.1 向量——vector

  • 这里提到了()和[]的区别,圆括号是n个向量,中括号是n个空向量的数组。
  • vector是一种能赋值的简单对象。当向量存有许多元素时,这种看起来无害的赋值和初始化的代价也可能很高。

3.7.5 标准容器

标准库容器说明
vector变长向量
list双向链表
stack堆栈
queue队列
deque双端堆栈
priority_queue按值排序的队列
set集合
multiset值可重复集合
map关联数组
multimap关键字可重复的关联数组

3.8.1 迭代器的使用

  • 这里出现了typename,继续补概念吧。假设有一个T::iterator *iter,T必须等到模板实例化时才会知道是哪种类型,更不用说内部的iterator,它可能是静态数据成员,静态成员函数或嵌套类型。嵌套类型的话就是T下的一个结构,但是如果是静态数据成员,iter就是一个函数。这样就会产生歧义。为了避免这种情况,typename告诉编译器这是类型而不是变量。

3.8.6 标准库算法

下面是其中觉得特别有用的东西

标准库算法说明
for_each()对每个元素调用函数
find()找出参数的第一个出现
find_if()找出第一个满足谓词的元素
count()统计元素的出现次数
count_if()统计与谓词匹配的元素
replace()用新值取代元素
replace_if()用新值取代满足谓词的元素
copy复制元素
unique_copy()复制元素,不重复
sort()对元素排序
equal_range()找到所有具有等价值的元素
merge()归并排序的序列

总结

  • 讲道理,对这一章的消化还不是很清楚,估计以后还要回头细看。
    

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台