模板是C++中非常重要的组成部分,之前自己对这块领域一直不太熟悉。最近趁着有时间学习了一下,特此总结。

首先是函数模板,它的定义方式如例子所示:

  1. template <typename T>T sum(T a,T b)
  2. {
  3. return a+b;
  4. }

类也有自己的模板,称为类模板,如下所示:

  1. template <typename T>class Proxy
  2. {
  3. public:
  4. typedef T value_type;
  5. Proxy();
  6. ~Proxy();
  7. value_type val;
  8. };
  9.  
  10. template<typename T> Proxy<T>::Proxy()
  11. {
  12. val=T(10);
  13. }
  14.  
  15. template<typename T> Proxy<T>::~Proxy()
  16. {
  17.  
  18. }

 要特别注意的是,C++中类模板的声明和定义应当放到同一个.h文件下,不能将声明和定义分散在不同的文件中。

类模板也可以有自己的友元函数和静态变量:

  1. template <typename>class Proxy;
  2. template <typename T>bool operator==(const Proxy<T>&,const Proxy<T>&);
  3. template <typename T>class Proxy
  4. {
  5. public:
  6. typedef T value_type;
  7. Proxy();
  8. ~Proxy();
  9. void printval();
  10. friend bool operator==<T>(const Proxy<T>&,const Proxy<T>&);
  11. value_type val;
  12. static T abc;
  13. };
  14. template<typename T> void Proxy<T>::printval()
  15. {
  16. std::cout<<val<<std::endl;
  17. }
  18. template <typename T> T Proxy<T>::abc=0;

无论是模板类还是普通类,都可以有自己的模板函数,编译器会根据具体代码的内容实例化特定的模板成员函数。

  1. template <typename T>class Proxy
  2. {
  3. public:
  4. template<typename U>void printNum(U num);
  5. };
  6.  
  7. template<typename T>template<typename U>void Proxy<T>::printNum(U num)
  8. {
  9. std::cout<<num<<std::endl;
  10. }

  当我们引用模板函数的时候,编译器利用调用中的函数实参来确定其模板参数,这叫做模板实参推断。但只有有限的几种类型转换会自动地应用于这些实参(const转换、数组或函数指针转换)。拿一段代码来举个例子:

  1. template <typename T>T sum(T a,T b)
  2. {
  3. return a+b;
  4. }
  5.  
  6. sum(10,10.5);//this code is error!

在引用sum的时候,实参一个是int类型,一个是double类型,此时不能像普通函数一样实现类型转换。以上代码在编译器是不通过的。

而如果先将函数显示实例化,则就可以实现参数类型转换了:

  1. sum<int>(10,10.5);

当我们不能(或不希望)将模板定义用于某些特定类型时,模板特例化就派上用场了。模板特例化就是一个用户提供的模板实例,它将一个或多个模板参数绑定到特定类型或值上。比如之前定义的sum函数,可以针对Sale_Data类特例化:

  1. template<>
  2. Sale_Data sum(Sale_Data a,Sale_Data b)
  3. {
  4. Sale_Data c;
  5. c.index=a.index+b.index;
  6. return c;
  7. }

这样一来,当我们为Sale_Data调用sum时,编译器就会采用上面这个函数;而不再使用通用的模板函数。

另外还需要记住typename的使用,如下面例子所示:

  1. template <typename T>class A
  2. {
  3. public:
  4. struct AS{};
  5. };
  6.  
  7. void test()
  8. {
  9. typename A<int>::AS as;
  10. }

此时在test函数中,如果我们不加typename,那么编译器无法确认AS到底A中的一种类型还是一种静态变量,因此需要用这种方式来声明。

例外情况如下所示:

(1)类模板定义中的基类列表

  1. template<class T>
  2. class Derived: public Base<T>::XXX
  3. {
  4. ...
  5. }

(2)类模板定义中的初始化列表

  1. Derived(int x) : Base<T>::xxx(x)
  2. {
  3. ...
  4. }

为什么这里不需要呢?因为编译器知道这里需要的是类型还是变量,(1)基类列表里肯定是类型名,(2)初始化列表里肯定是成员变量名。

C++模板机制总结的更多相关文章

  1. ectouch第七讲 之ECshop模板机制整理

    网上的资源感觉还是有些用,可以看看,帮助理解,ECshop模板机制整理原文:http://blog.sina.com.cn/s/blog_6900af430100nkn8.html 一.模板引擎: E ...

  2. ECshop模板机制

    ECshop模板机制整理 模板机制 近期新项目涉及到ECshop的二次开发,趁此良机正好可以对闻名已久的ECshop系统进行深入了解.要了解一个系统,那么该系统的模板机制就是最重要的一环.相关整理如下 ...

  3. C++编译器模板机制剖析

    思考:为什么函数模板可以和函数重载放在一块.C++编译器是如何提供函数模板机制的? 一.编译器编译原理 什么是gcc gcc(GNU C Compiler)编译器的作者是Richard Stallma ...

  4. C++模板 · 为什么要引入模板机制?

    刚学过类模板时,很不理解,甚至觉得这简直没有用,在自己骗自己嘛!明明很方便的东西,偏偏要加个类模板来回折腾.可能因为我们刚开始写的程序很简单,有时候,可能程序复杂一点,对理解一些概念更有帮助. 今天在 ...

  5. C++11程序设计要点总结-模板机制详解

    C++程序设计要点总结 在编程的过程中呢我们总会遇到一些各种各样的问题,就比如在写方法的时候,我们一个同样的方法要写好几种类型的呢,这让我们很伤脑筋,但是呢C++有一个强大的功能就是模板机制,这个模板 ...

  6. WPF源代码分析系列一:剖析WPF模板机制的内部实现(一)

    众所周知,在WPF框架中,Visual类是可以提供渲染(render)支持的最顶层的类,所有可视化元素(包括UIElement.FrameworkElment.Control等)都直接或间接继承自Vi ...

  7. ecshop 模板机制

    ECShop模板是基于smarty 文件名cls_template.php lib_main.php中的assign_template()会设置我们的网店的公共信息及网站设置:assign_dynam ...

  8. C++(四十三) — 函数模板机制

     1.普通函数与模板函数调用原则 函数模板可以像普通函数一样被重载: 当函数模板和普通函数都符合条件时,编译器优先考虑普通函数: 但如果函数模板产生一个更好的匹配,则选择函数模板: 可以通过空模板实参 ...

  9. laravel模板机制

    @extends('layouts.master') @section('title', 'Page Title') @section('sidebar') @parent <p>This ...

随机推荐

  1. SQLite数据库在多线程写锁文件的解决办法

    参考了很多SQLITE数据库多线程的解决办法 我自己写了一个SQLITEHELPER 来解决这个问题 希望大家多多指教 调用的时候  SQLLiteDBHelper _SQLLiteDBHelper ...

  2. 用户 NT AUTHORITY\NETWORK SERVICE 登录失败 解决方法(转载)

    用户 NT AUTHORITY\NETWORK SERVICE 登录失败 解决方法 (MS SQL 2005) Windows server 2003,2008 Web.Config 配置连接sql ...

  3. Java 在指定目录建立指定文件名的文件 并输入内容

    package runoob; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream ...

  4. in a devstack Openstack env, how to start a service, such as aodh-listener

    in terminal, when start the service, the service will run in this terminal, and if kill this termina ...

  5. Spike Notes on Theory of (Software) Transactional Memory[Doing]

    Motivation 程序员是否需要在处理一致性问题或者同步时,一定要make hands dirty?能不能专注于应用级原子性,而无需考虑低层操作系统.运行时支持的原子性概念或者语言构造? 软件事务 ...

  6. Oracle cmd 导出数据库或者表定义或者纯数据

    实例: expdp zypacs/Sfx371482@zyrisdb schemas=ZYPACS content=metadata_only CONTENT={ALL | DATA_ONLY | M ...

  7. SQL Server 2008安装过程中的一些问题和心得

    开博客已经好久了,但一直没有用起来,也有很多"老人"劝诫我,好记性不如烂笔头,于是一年后的我重拾博客,打算记录一些我在计算机方面遇到的一些问题和心得. 前几天重装了Win10系统, ...

  8. APP邂逅即时通讯云,让你的手机APP聊起来

     #推荐活动# #线下沙龙# 明天下午在IC咖啡 —— <APP邂逅即时通讯云,让你的手机APP聊起来>, http://url.cn/Y8sYo5 

  9. Android NDK几点回调方式

    一.NDK中获取android设备ID的方式 Java代码如下(获取设备ANDROID_ID): final String androidId = Secure.getString(context.g ...

  10. 为什么js加事件时不要写括号

    function al(){alert("我擦")}此时,al代表这个函数的对象,al()就是直接运行了.var nfun=al;就是让nfun也指向了al,此时nfun()就相当 ...