学艺不精而惭愧--论C++模板类的使用

自己断断续续地使用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.

原文地址:https://www.cnblogs.com/llguanli/p/8450036.html

时间: 2024-10-09 00:38:23

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

学艺不精而羞愧--论C++模板类的使用

自己断断续续地使用C++也有一段时间了,有些时候产生了自满的情绪,认为自己对C++的语言特性已经知道的差不多了,在语法方面没有什么难倒我的地方了,现在所要做的是根据实际问题编写程序,问题的难点在于算法的设计和分析,在于解决问题的策略了.然而今天下午的一次经历给自己当头一棒:永远不要自满,要保持一颗谦虚的学习的心. 1 问题的产生 我在实现[书][1]中219页的list的contiguous结构时,按照我的惯性,写了两个文件:rblist.h和rblist.cpp,分别为类定义和方法的具体实现.

模板类的友元重载

模板类的友元重载和普通类的友元重载有不同之处,可以参考这篇CSDN博客http://blog.csdn.net/ozwarld/article/details/7770808 #include <iostream> using namespace std; template <class T> class Test; // 模板类前置声明 template<class T> ostream& operator << (ostream& out

C++ 模板函数与模板类

一.模板函数 函数模板提供了一类函数的抽象,即代表了一类函数.当函数模板被实例化后,它会生成具体的模板函数.例如下面便是一个函数模板: 当实际调用它时,就会生成具体的模板函数:    模板函数在调用过程中会进行数据类型的自动匹配(在不产生歧义的情况下),但如果需要指定类型的话,可以显示声明,如: 这样,函数模板中的T就会被double所代替. 自动匹配有以下的规则: 1) 函数实参是否满足模板的实参(此时的判断没有数据类型的转换): 2) 若不满足1), 函数实参进行数据转换在进行匹配: 3)

一个数组类【模板类】

这学期的大作业感觉挺简单的,就是写一个模板类MyList,实现一些Python中的list的操作(类似于c++中的vector,但是不支持迭代器).这些功能都很简单,唯一麻烦的就是模板类特别烦,特别是友元函数,首先要声明这个类,然后声明是函数的声明,然后是类中友元函数的声明,最后是实现.友元函数的声明还有一个问题就是声明时在函数名后面要加上一个<>就像这样: friend void Qsort<>(T a[],int low,int high,bool less); 还有一个要注意

第六周项目6-复数模板类

阅读教材例10.1.该例实现了一个复数类,但是美中不足的是,复数类的实部和虚部都固定只能是double型的.可以通过模板类的技术手段,设计Complex,使实部和虚部的类型为定义对象时指定的实际类型. (1)要求类成员函数在类外定义. (2)在此基础上,再实现减法.乘法和除法 你可以使用的main()函数如下. int main( ) { Complex<int> c1(3,4),c2(5,-10),c3; //实部和虚部是int型 c3=c1.complex_add(c2); cout<

C++中的链表节点用模板类和用普通类来实现的区别

C++中的链表节点通常情况下类型都是一致的.因此我们可以用模板来实现. #include <iostream> using namespace std; template<typename Type>//定义一个模板类必须有的声明 class LinkNode //表示链表节点的类 { public: LinkNode() :m_pnext(nullptr){}//构造函数,在函数体内实现的相当于默认在前面加了inline关键字修饰 LinkNode(Type item, Link

模板类的定义和实现可以不在同一个文件中

写c++程序时我们经常会把函数的定义写在xxx.h中,把函数的实现写在xxx.cpp, 但是当我们写带模版的函数和类时,这样写 就会出现问题,如下: stack.h //stack.h #ifndef STACK_HPP #define STACK_HPP #include <vector> #include <stdexcept> template<typename T, typename TContainer = std::vector<T>> clas

模板类的全特化、偏特化

我们先来定义一个普通的模板类 1 template<class T> 2 struct Test 3 { 4 Test(){ cout << "模板类" << endl; } 5 }; 我们再来调用一下: 1 int main() 2 { 3 Test<char> t1; 4 Test<int> t2; 5 Test<int *> t3; 6 return 0; 7 } 输出的结果1: 模板类 模板类 模板类 如果

Vector模板类

1 #include "stdafx.h" 2 typedef int Rank; //秩 3 #define DEFAULT_CAPACITY 3 //默认的初始容量(实际应用中可设置为更大) 4 5 template <typename T> class Vector 6 { //向量模板类 7 protected: 8 Rank _size; int _capacity; T* _elem; //规模.容量.数据区 9 void copyFrom(T const* A