摘要:前言 封装性,继承性,多态性是面向对象语言的三大特性。其中封装,继承好理解,而多态的概念让许多初学者感到困惑。本文将讲述C++中多态的概念以及多态的实现机制。什么是多态? 多态就是多种形态,就是许多情况下可以互换地使用基类型和派生类型的多种形态。多态的实现 依赖于动态绑定机制动态绑定机制相关 ...
阅读全文
摘要:前言 学习C++标准算法时,我们知道带有_if的算法都带有一个谓词函数。此前我们直接使用函数名充当谓词函数,这样做有很大的局限性( 下文会做分析 )。为此本文将介绍C++中一个新的技术:函数对象。用它来充当谓词函数就能解决这个问题。什么是函数对象? 函数对象就是重载了函数调用操作符的对象。我们知...
阅读全文
摘要:前言 有书这么说过,C++设计的最大目的在于允许程序员定义自己的类型,并使它们用起来跟内置类型一样容易和直观。就目前看来,要实现这一点,最核心的莫过于操作符的重载。科学的重载可以让类的使用最大程度地接近内置类型。本文将讨论类操作符重载涉及到的一些原则和具体做法。实现类操作符重载的两种思路 1. ...
阅读全文
摘要:前言 经过前两篇随笔( 上 中 )的分析我们已经解决了具有指针成员的同类对象“ 干涉 ”问题。可惜,前面给出的解决方案代码还是不完整。还有什么问题呢?观察发现,构造函数里面有new的关键字出现,也就是说开辟了新的内存空间,我们也知道new必须也只能对应一个delete,而不应该让系统自己处理( 还...
阅读全文
摘要:前言 先思考一下上一篇随笔前言中提出的问题。请问:仅仅自定义了复制函数就可以避免带有指针成员的同类对象相互干扰吗?很遗憾,还不够。请思考以下情形( A中依然带有指针成员 ):A a1; A a2; a1 = a2; 在最后一句执行时,复制函数并不会启用( 这种情况启用的是默认的赋值运算符 ),因此...
阅读全文
摘要:前言 若要将a对象复制给b对象,编译器应当做何工作?C++初学者也许会直接说” a对象的成员复制给b对象的成员 “。在很多情况下,这种说法正确,事实上C++会给类定义一个默认的复制函数,它所做的工作也正是如此。但,下面问题来了:如果类的成员当中有指针,这种做法还行吗?本文将对这个问题作出实例分析。...
阅读全文
摘要:前言 C++提供了很多算法(超过一百个),要想掌握这些算法的使用需要将它们都死记下来吗?当然不用了,本文将为你剖析泛型算法的基本结构,让你以后对这些算法做到“ 望名生义 ”。算法的形参结构 绝大多数算法的形参采用以下四种形式之一: 1. 算法名 ( 起始迭代器, 末端迭代器, 其他参数 ) 说明:起始迭代器和末端迭代器标识了算法的输入范围,其他参数与算法特性有关。 2. 算法名 ( 起始迭代器, 末端迭代器, 插入迭代器/流迭代器, 其他参数 ) 说明:起始迭代器和末端迭代器标识了算法的输入范围,插入迭代器/流迭代器标识了输出对象(其范围假定和输入范围一样大),其他参数与算法特性有...
阅读全文
摘要:前言 标准算法配合迭代器使用太美妙了,使我们对容器(数据)的处理更加得心应手。那么,能不能对IO流也使用标准算法呢?有人认为不能,他们说因为IO流不是容器,没有迭代器,故无法使用标准算法。他们错了,错在IO流确实不是容器,但它能绑定一种特殊的迭代器,叫做流迭代器。一些算法能以流迭代器为参数,对IO...
阅读全文
摘要:前言 本文将讲解一个经典的文本查询程序,对前面所学的容器相关知识进行一个从理论到实际的升华,同时也对即将学习的面向对象知识来一次初体验。程序描述 要求实现这样一个程序:读取用户指定的文件,然后允许用户从中查找某个单词所在的位置。一个面向过程的落后的设计思想 将待检索文件以行为单位存放到Vect...
阅读全文
摘要:前言 multimap容器是map容器的“ 增强版 ”,它允许一个键对应多个值。对于map容器来说,find函数将会返回第一个键值匹配元素所在处的迭代器。那么对于multimap容器来说,find函数将如何运作呢?如果要实现和map容器的find函数同样的功能,则它将返回多个迭代器,这样太复杂了。...
阅读全文
摘要:前言 我们可以用下标访问顺序容器的元素,也就是说在顺序容器实现中下标和元素的值相关联。那么能不能让别的值(而不是下标)与元素的值相关联呢?有的,实现这种功能的容器就叫做关联容器,而关联的本质就是某个特定的“键”与元素的值相关联。常见的关联容器 1. map:也即关联数组,是键 - 值的集合 2...
阅读全文
摘要:前言 vector容器的数据结构原型是顺序表,它很好的实现了顺序表的功能,大大方便了编程。好了,现在假设有天我又想用栈,那么有没有栈对应的容器呢?很遗憾,木有。但基于“栈”可以由顺序表或者链表实现这一特性,C++提供了stack给我们使用,来解决栈的实现这个问题。stack可不是类,也不是容器,那...
阅读全文
摘要:前言 常见的顺序容器主要有三种 - vector,deque,list。它们实现的功能相差不大,那么实际开发中该如何进行选择呢?本文将为你解答这个问题。分析 由于这三种容器实现的数据结构原型不同(vector实现原型是顺序表,deque是双端队列,list是链表),因此这三种容器对插入删除以及访问操作的开销是不同的。为了编制出高效的程序,我们应当通过分析容器操作的开销来选择容器。访问操作对容器选择的影响 1. vector容器的随机访问效率最高 2. deque容器的随机访问效率也高 3. list容器的随机访问效率低插入删除操作对容器选择的影响 1. vector容器只是在尾部...
阅读全文
摘要:前言 容器是指容纳特定类型对象的集合。顺序容器则是指该容器根据位置访问保存在其中的对象。Vector,List,Deque是三种常见的容器,本文将归纳这三种容器常用的函数,以备日后查阅。描述符说明 在以下函数解释中,C 表示容器类型名,T表示容器的元素类型,c 表示待创建的/待处理的容器对象,其它描述符则在文中具体位置说明。一 容器定义函数 1. C c 创建一个空的容器 c 2. C c( c2 ) 用 容器c2 创建 容器c 3. C c( b, e ) 用 迭代器 b 和 e 之间的元素创建容器 c。 下函数4,5仅用于顺序容器: 4. C c( n, t ) 创建...
阅读全文
摘要:前言 字符串流对象有个很实用的功能就是格式转换。比如可以将整数类型的123转换成字符串格式的123,或者反过来。那么具体又是如何实现的?且看下文。实现思路 对于整数转换成字符串格式,可设s是一个空的字符串流对象,” 整型变量 “存放目标整数。则当执行" s > 整型变量 “。此后该整型变量既是目...
阅读全文
摘要:前言 本文分析两个经典的C++文件IO程序,提炼出其中文件IO的基本套路,留待日后查阅。程序功能 程序一打印用户指定的所有文本文件,程序二向用户指定的所有文本文件中写入数据。程序一代码及其注释 1 #include 2 #include // 使用文件处理对象记着要包含这个头文件 3 #include 4 #include 5 6 using namespace std; 7 8 int main() 9 {10 /*11 * 获取用户需要打开的所有文件名,将其保存在顺序容器files中。12 */13 string filename;14...
阅读全文
摘要:前言 你是否遇到过以下情况? 情况一:为了调试方便,代码中夹杂各种cout语句。当调试好了,把这些语句删了,运行“正式版”后,又发现新问题,只得把这些cout语句一个个添加回去再进行调试。如此不断循环。 情况二:希望在代码中获取到源文件的文件名,当前代码行号,编译时间等信息。 情况三:纠结于...
阅读全文
摘要:前言 对于隐式转换,想必你已经了解了算数转换中的“ 向上对齐 ”的概念;了解了赋值隐式转换的规律( 右值类型转换为左值类型 )。但C++中的隐式转换远不止这些,本文就将告诉你一些容易被忽略,但事实上发生了的隐式转换。一 数组转换为指针 在许多情况下,数组都隐式转换为了指针。取数组元素的过程就是根据首元素和元素序号以及元素大小到指定位置取值;数组作为函数参数传递给函数的过程中也转换成了指向首元素的指针。当然,在一些其他的场合,隐式转换未必发生,比如sizeof( 数组 )就不会隐式转换为sizeof( 指针 )。二 逻辑判断中其他变量向布尔类型隐式转换 if ( p ), while ( ...
阅读全文
摘要:前言 new和delete是C++中用来动态管理内存分配的运算符,其用法较为灵活。如果你对它们的几种不同用法感到困惑,混淆,那么接着看下去吧。功能一:动态管理单变量/对象空间 下面例子使用new为单个变量/对象开辟空间:1 // 创建一个指向整型元素的指针pi,其所指对象为整数100。2 int *pi = new int(100); 3 4 // 创建一个指向字符串元素的指针ps,其所指对象为字符串"ssssssssss"。5 string *ps = new string(10, 's'); 对于开辟的单变量/对象空间,我们只能通过new操作符返回的指针
阅读全文
摘要:前言 阅读C++教材时,想必你听过复制初始化,直接初始化,值初始化这三个概念吧。笔者本人常将其混淆,遂在此记录下它们的具体含义以便日后查阅。复制初始化( copy-initialization ) 复制初始化使用 = 对变量进行初始化直接初始化( direct-initialization ) 直接初始化用把初始化式子放到括号中的方式对变量进行初始化值初始化( value-initialization ) 值初始化和上面两种初始化是不同的概念。上两种初始化说明的是“ 用什么样的语法格式来初始化变量 ",而值初始化不但要说明“ 用什么样的语法格式来初始化变量 "( C++中用
阅读全文