自己断断续续地使用C++也有一段时间了。有些时候产生了自满的情绪。觉得自己对C++的语言特性已经知道的几乎相同了,在语法方面没有什么难倒我的地方了,如今所要做的是依据实际问题编敲代码,问题的难点在于算法的设计和分析。在于解决这个问题的策略了。

然而今天下午的一次经历给自己当头一棒:永远不要自满,要保持一颗谦虚的学习的心。

1 问题的产生

我在实现[书][1]中219页的list的contiguous结构时。依照我的惯性,写了两个文件:rblist.h和rblist.cpp,分别为类定义和方法的详细实现。rblist.h中包括了模板类的定义。我又写了測试程序testList.cpp来測试这个连续存储的表结构时遇到了麻烦。

我使用的编译命令为:

g++ Utility.cpp rblist.cpp testList.cpp -o testList

而在testList.cpp中我使用的是#include "rblist.h"这条预处理指令。编译出错例如以下:



我前后几次确认代码没错,检查几遍还是编译不通过。我又将rblist中的代码删减到只剩一个方法仍然编译只是。没办法唯独通过网上搜索解决的方法了。果真找到了解决的方法。代码和编译命令保持不变。而只将testList.cpp中的包括指令改为#include "rblist.cpp"就顺利通过编译了。

我对预包括指令包括cpp文件的做法感到非常奇怪。

我从没见过常常包括头文件的命令可以用于包括cpp文件,并且可以保证编译成功。并且网上的那位朋友指出,这是使用模板类easy犯的错误。我对此产生疑问。在我所读过的不论什么教科书中,从没见过#include "rblist.cpp"这样的用法,我也对这样的用法感觉非常的不舒服。

我决定对该问题一探到底。

2 对模板类用法的在认识

我曾经读过[Bruce Eckel的书][2],对当中关于template class的介绍已经模糊了。但凭我的直觉。一定不会使用#include "rblist.cpp"这样的方法来使用模板类,其实也正验证了我的直觉。该书给出了4中方法使用模板类:

  1. Inline function definition: 将方法的定义写在类的声明中,同一时候将main()函数与该模板类写在同一个文件里。这样的方法简单易用,通常出如今教科书中,实际的project项目中根本不会用这样的方式使用模板类。初学C++的时候我按此方法练习了模板类的使用。也正是由于此方法让我误觉得我已经掌握了模板类的用法。

  2. Non-inline function definitnion: 该方法将类函数定义在类声明的外部,函数定义和类声明仍然在同一个文件里。同一时候用于測试的main()函数也在同一文件里。最后整个文件为cpp文件。这样的方法给出了模板类的定义的新视角。将函数从类声明分离出去。但由于它们仍然在同一文件里,在源文件头部仍然不须要出现#include 模板类的命令。

    这样的方法以及前一种方法不会产生本文遇到的问题。

  3. Header files: 这样的方法将整个模板类声明和定义统一写于一个头文件.h中。原文这样说: “Don’t put in anything that allocates storage,”, but template definitions are special. Anything preceded by template<..> means the compiler won’t allocate storage for it at that point, but will instead wait until it’s told to. So you’ll almost always put the entire template declaration and definition in the header file, for ease of use. 我採用此方法又一次写了一个文件rbList2.h文件,将模板里List的声明和定义统统写在里面。然后使用#include "rblist2.h"将其包括在testList.cpp中。使用g++ Utility.cpp testList.cpp -o testList编译,顺利通过编译。我是比較认可这样的方式使用模板类的。我看到曾经阅读[书][2]时对应的句子上面做的标记,但是一到实际的问题中,还是把它忘记的一干二净。

    看来。要想学好语言,光看不练是不行的,要在看基本知识的前提下多多编程,通过实际编程经验来提高编程能力。比方,我编程中遇到本文的问题,回头来在去看曾经看过的书,经过这样一个循环重复的过程后,对对应的问题理解的就深刻了。

    曾经初学时候觉得非常难、非常高大上的概念和知识点就变得非常easy了。

    知道了该概念出现的背景,它给编程人员带来的优点等等,比只知道怎样详细的用要理解的深刻的多,并且也不会遗忘。

  4. [Bruce Eckel][2]也提到了模板类的声明和定义分别写在.h文件和.cpp文件里的做法,但这只为了产生dll而不得不做的妥协的做法,指出该方法须要參考详细的编译器规定。这样的方法非常少见。我想这可能就是#include "rblist.cpp"这样的用法吧。

3 感悟

通过今天这个经历,使我认识到:

  1. 永远保持一颗谦虚的心非常重要。

    不要自满。在该学习的地方停止学习了。

  2. 学习编程的最好的做法就是多多编程。编的越多,当中感觉神奇的地方就会变得越来越少了,自己也就会越来越充实。

[1]: Robert L. Kruse and Alexander J. Ryba. Data Structures and Program design in C++. Upper Saddle River, 2000.

[2]: Bruce Eckel. Thinking in C++ Volume 1. 2nd. 2000.

学艺不精而惭愧--论C++模板类的使用的更多相关文章

  1. STL标准模板类

    STL,中文名标准模板库,是一套C++的标准模板类(是类!),包含一些模板类和函数,提供常用的算法和数据结构. STL分为:迭代器,容器,适配器,算法以及函数对象. --迭代器是一种检查容器内元素并遍 ...

  2. 单链表的C++实现(采用模板类)

    采用模板类实现的好处是,不用拘泥于特定的数据类型.就像活字印刷术,制定好模板,就可以批量印刷,比手抄要强多少倍! 此处不具体介绍泛型编程,还是着重叙述链表的定义和相关操作.  链表结构定义 定义单链表 ...

  3. 模板类 error LNK2019: 无法解析的外部符号

    如果将类模板的声明和实现写在两个独立的文件中,在构建时会出现"error LNK2019: 无法解析的外部符号 "的错误. 解决方法有: 第一种方法,就是把类模板中成员函数的声明和 ...

  4. 关于g++编译模板类的问题

    今天搞了我接近4个小时,代码没错,就是调试没有通过,无论怎么也没有想到是编译器的问题 g++不支持c++模板类 声明与实现分离,都要写到.h文件里面. 以后记住了.

  5. C++11特性(模板类 initializer_list)

    [1]initializer_list模板类 C++primer 原文如下: 通读原文相关篇幅,分析解读内容如下: 提供initializer_list类的初衷,为了便于将有限个同一类型(或可转换为同 ...

  6. C++11模板类使用心得

    1.推荐使用std::shared_ptr<TaskT>代替指针TaskT*使用,shared_ptr是一种智能指针,能自主销毁释放内存,在c++11中被引入,在多线程编程中有很大的用处, ...

  7. c++模板类

    c++模板类 理解编译器的编译模板过程 如何组织编写模板程序 前言常遇到询问使用模板到底是否容易的问题,我的回答是:“模板的使用是容易的,但组织编写却不容易”.看看我们几乎每天都能遇到的模板类吧,如S ...

  8. C++ 模板函数与模板类

    一.模板函数 函数模板提供了一类函数的抽象,即代表了一类函数.当函数模板被实例化后,它会生成具体的模板函数.例如下面便是一个函数模板:

  9. 模板类重载<<运算符

    写了一个Matrix模板类,需要重载<<, 1.需要友元函数 2.需要此函数的实现在.h中(本人试验出来的,放在.cpp中编译不通过) template <typename T> ...

随机推荐

  1. 3-3 第三天 Promise 如何使用

    回调的方式来处理异步,目的是要保证一个执行顺序,先完成什么再去完成什么,它们的作用其实是相同的,显然回调更容易来书写,但是它难以维护,很容易遗漏错误处理代码而且无法使用return语句来返回这个值. ...

  2. 【转】Java的可变类与不可变类

    1.可变类和不可变类(Mutable and Immutable Objects)的初步定义: 可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容. 不可变类:当你获得这个类的一个实例引 ...

  3. win10 + vs2017 + vcpkg —— VC++ 打包工具

    vcpkg 是微软 C++ 团队开发的在 Windows 上运行的 C/C++ 项目包管理工具,可以帮助您在 Windows 平台上获取 C 和 C++ 库. vcpkg 自身也是使用 C++ 开发的 ...

  4. BZOJ 1018 线段树维护图的连通性问题

    思路: 我们可以搞一棵线段树 对于一段区间有6种情况需要讨论 左上右下.左上右上.左下右下.左下右上 这四种比较好维护 用左上右下举个例子吧 就是左儿子的左上右下&左区间到右区间下面有路&am ...

  5. Elasticsearch之curl创建索引库和索引时注意事项

    前提, Elasticsearch之curl创建索引库 Elasticsearch之curl创建索引 注意事项 1.索引库名称必须要全部小写,不能以下划线开头,也不能包含逗号 2.如果没有明确指定索引 ...

  6. KAFKA 调优

    KAFKA 调优 最近要对kafka集群做调优,就在网上看了些资料,总结如下. 我们的kafka版本是0.10.1.0. 机器配置是40G内存,300G硬盘. 一共有3台机器组成一个小的集群. Kak ...

  7. 12) 十分钟学会android--APP通信传递消息之简单数据传输

    程序间可以互相通信是Android程序中最棒的功能之一.当一个功能已存在于其他app中,且并不是本程序的核心功能时,完全没有必要重新对其进行编写. 本章节会讲述一些通在不同程序之间通过使用Intent ...

  8. 【华科考研机试题】最长&最短文本

    题目 输入多行字符串,请按照原文本中的顺序输出其中最短和最长的字符串,如果最短和最长的字符串不止一个,请全部输出. 解题思路 1.输入所有字符串(有空格不另算字符串). 2.将char*字符串转换成s ...

  9. hdu2121 Ice_cream’s world II 最小树形图(难)

    这题比HDU4009要难一些.做了4009,大概知道了最小树形图的解法.拿到这题,最直接的想法是暴力.n个点试过去,每个都拿来做一次根.最后WA了,估计是超时了.(很多题都是TLE说成WA,用了G++ ...

  10. 【Oracle】SCOPE=MEMORY|SPFILE|BOTH

    SCOPE=MEMORY|SPFILE|BOTH 指示了修改参数时的“作用域”: SCOPE=MEMORY :只在实例中修改,重启数据库后此次修改失效. SCOPE=SPFILE :只修改SPFILE ...