(转载请注明原创于潘多拉盒子)

  C++是强类型语言,而且恐怕是强类型语言里面类型最严格的。这意味着:1. C++变量的类型在定义时就确定了;2. 该类型在后续的生命期中不会改变。比如:

int n = 0;
n = 3.14159; // n的类型不变,仍然为int型

这样编译器产生的机器码是确定的,不需要运行时编译,比如像Python中的JIT(Just In Time)那样在代码执行过程中编译。

  但是,这给代码的可复用性带来了麻烦。比如现实中我们可能会定义一个二元关系"<",它表示“如果a < b,那么a在b前面”,或许你可以简单的理解为小于号,或者更广义的说,是a在b前面。那么你可能可以基于这个顺序的定义写一个排序函数。比如:

void sort(int* array, int len)
{
// 某种排序实现,比如冒泡或者快速排序,就地对array中的元素进行排序
}

貌似就OK了!但仔细一看,不对!如果array是double型呢?幸好C++有重载(overload)机制,这事儿也不难:

void sort(double* array, int len)
{
// 某种排序实现,比如冒泡或者快速排序,就地对array中的元素进行排序
}

由于是sort是完全基于 "<"运算符的,因此可以想想这两段实现代码看起来会非常像,出了中间变量的类型不同之外,其余都是相同的。甚至你可以直接拷贝粘贴,可以轻松实现float、long甚至是string的排序函数。

  不过,这很繁琐,不仅如此,还带来了维护的问题,如果代码需要改动呢?C++为解决这类问题,提供了模版机制,它允许程序员用"抽象类型"来暂时替代具体的类型,比如上述的例子可以写成:

template <typename T>
void sort(T* array, int len)
{
// 直接实现基于抽象类型T的排序函数,这里的类型T是可以在编译时确定的
}

注意,这段代码必须实现在头文件中,不可以实现在cpp中,除非该函数仅仅由该cpp调用。有了这样一个函数的定义,在客户代码中如何调用呢?该怎么调用就怎么调用,比如:

 std::string names[100];
// load names ...
sort(names, 100); // 编译器在此时完成模版的实例化

  除了可以定义模版函数之外,还可以定义模版类,比如标准模版库(STL)就是基于模版机制实现的C++标准库。比如你可以定义一个类Any(boost库中有完整的实现boost::any),用于封装所有的类型。这个类可以定义成这样:

class Any
{
public:
Any() : _object(NULL), _type() {} Any(const Any& other) : _object(other._object), _type(other._type) {} Any& operator = (const Any& other)
{
    _object = other._object;
    _type = other._type;
return *this;
} // 可以将任意类型T的对象存储在这个Any类型中
  template <typename T>
  Any& operator = (const T& object)
  {
    _holder = new T(object);
    _type = typeid(T);
return *this;
  } // 定义了向已知类型T的转换操作
  template <typename T>
  T& cast()
  {
    if (typeid(T) != _type)
    {
      throw std::exception("bad type");
    }
    return *reinterpret_cast<T>(_object);
  } private:
void* _object;
std::type_info _type;
};

这个类使用起来是这样的:

std::string name = "ZHANG San";
Any attribute = name; // 这个any内部保存的类型被实例化为std::string
std::string& anotherName = name.cast<std::string>(); // 由于没有参数列表,只能在模版实例化指示部分<std::string>定义实例化类型
assert(name == anotherName); // must be true

  或许,你需要定义一个容器类,像STL那样,保存某些元素:

template <typename T>
class Container
{
public:
// 具体定义
}; // 客户代码
Container<double> scores;

  

C++的模版机制较复杂,实际使用中也会遇到不少问题,这里因为内容深度的限制,就不继续讨论了。

C++的优秀特性5:模版的更多相关文章

  1. C++的优秀特性6:智能指针

    (转载请注明原创于潘多拉盒子) 智能指针(Smart Pointer)是C++非常重要的特性.考虑如下一段使用简单指针(Plain Pointer)的代码: A* a = new A(); B* b ...

  2. 总结Codeigniter的一些优秀特性

    总结Codeigniter的一些优秀特性 近期准备接手改进一个别人用Codeigniter写的项目.尽管之前也实用过CI,可是是全然按着自己的意思写的,没按CI的一些套路.用在公众的项目,不妨按框架规 ...

  3. C++的优秀特性1:引用

    (转载请注明原创于潘多拉盒子) 一本典型的C语言教科书的厚度大约是200页左右,而一本典型的C++教科书的厚度至少要500页.比如K&R的<The C Programming Langu ...

  4. C++反射机制:可变参数模板实现C++反射(使用C++11的新特性--可变模版参数,只根据类的名字(字符串)创建类的实例。在Nebula高性能网络框架中大量应用)

    1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法.该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能.Nebula框架在码云的仓库地 ...

  5. C++的优秀特性4:指针

    (转载请注明原创于潘多拉盒子) 其实指针不是C++的特性,而是地地道道的C的特性.有人说C++继承了C的指针,实在是败笔,造成内存泄漏云云,纯粹是不懂.可以这么说,如果没有指针,C++会逊色很多,应用 ...

  6. C++的优秀特性3:构造函数和析构函数

    (转载请注明原创于潘多拉盒子) 构造函数和析构函数是C++中再熟悉不过的概念了,几乎每个了解一点C++的人都知道这两个概念是什么意思.一个对象的全部生命期中构造函数和析构函数执行的时机如下: 1. 为 ...

  7. C++的优秀特性2:inline 函数

    (转载请注明原创于潘多拉盒子) Inline函数是C++的一个很小的特性,在不计较效率的情况下,这个特性似乎可有可无.然而,C++天生是为最为广泛的应用场景设计的,因此,总会有关于效率的问题.其实,除 ...

  8. Swiftl优秀的特性

    Swift语言在吸收诸多优秀语言如java.c++,Python之后.提供给开发人员大量优秀的特性. 以下我列举一下,swift一些优秀的特性: 1.函数使用经典的圆括号和点调用语法 2.函数标签特性 ...

  9. 关于js当中一些糟糕的特性

    首先,不可否认,js是一门具有许多优秀特性的弱类型语言,但是这门语言在设计之初就投入了工程实践,没有经历严格的实验室测试,以致力于它是如此的粗糙,在相当长的一段时间很不受开发者待见,被视为一门玩具性的 ...

随机推荐

  1. IOS OC声明变量在@interface括号中与使用@property的区别(转载)

    刚开始接触OC再看别人写的代码的时候,常常困惑于人家在声明属性时的写法,总结出来有三中方式,不知道哪一种比较规范化,现在我把三种方式贴出来,然后再一一探讨每个方式声明属性的区别. 方式一:直接在@in ...

  2. 打造万能的ListView GridView 适配器

    转载:http://blog.csdn.net/lmj623565791/article/details/38902805/ 通用的ViewHolder 首先分析下ViewHolder的作用,通过co ...

  3. Tesseract-OCR识别验证码

    1. 安装Tesseract-OCR,安装后测试下是否安装成功

  4. ChromePHP - Chrome浏览器下的PHP debug工具

    一款 Chrome 下用来配合调试 PHP 的工具,看官方介绍应该和 FirePHP 有异曲同工的.喜欢用Chrome 的PHPer 可以尝试一下. 官方网站:http://www.chromephp ...

  5. SQL Server 最小化日志操作解析,应用[手稿]

    Sql Server 中数据库在BULK_LOGGED/SIMPLE模式下的一些操作会采用最小化日志的记录方式,以减小tran log落盘日志量从而提高整体性能. 这里我简单介绍下哪些操作在什么样的情 ...

  6. 用代码将Excel数据导入Sql Server

    这里直接用小例子说明. 1.打开VS2010—>文件—>新建—>网站,选择ASP.NET空网站并设置存放路径以创建空网站.(我这里路径设置为D:\excelEduceToSql) 2 ...

  7. C语言部分

    1.内核的裁剪怎么裁剪 2.深入理解uboot 3.TCP/IP TCP/UDP原理是什么? 4.项目里你做了些什么?怎么做的?为什么要那样做? 5.指针与数组的用法及计算 6.单链表和双链表的用法 ...

  8. 数往知来 asp.net 聊天室问题解决方案<十六>

      1:在服务端创建了一个负责监听的sokcet   //三个:采用TCP协议.              ListenSocket = new Socket(AddressFamily.InterN ...

  9. 黑马程序员——OC的内存管理学习小结

    内存管理在Objective-C中的重要性就像指针在C语言中的重要程序一样. 虽然作为一门高级语言,但OC却没有内存回收机制.这就需要开发者来对动态内存进行管理.OC中内存管理的范围是:任何继承了NS ...

  10. JavaScript高级程序设计(第三版)第五章 引用类型

    5.2 Array类型 var colors = new Array(3); //创建一个包含3项的数组 var names = new Array("Greg"); //创建一个 ...