1,预备知识:

1,模板参数可以是数值型参数(非类型参数):

1,代码示例:

 template <typename T, int N>
void func()
{
T a[N]; // 使用模板参数定义局部数组;
} func<double, >(); // 使用模板时,数值型参数必须是常量,不能是变量;

2,数值型模板参数的限制:

1,变量不能作为模板参数;

1,是变量的话就不满足准确确定的这个本质;

2,浮点数不能作为模板参数;

1,浮点数本身不精确;

3,类对象不能作为模板参数;

1,类对象编译时不能唯一确定的,同变量一样;

3,数值型参数本质:模板参数是在编译阶段被处理的单元,因此,在编译阶段必须准确无误的唯一确定;

2,有趣的面试题:

1,用你觉得最高效的方法求 1 + 2 + 3 + ... + N 的值;

1,等差数列和的方式;

2,见下面实例;

3,数值型模板参数编程实验:

 #include <iostream>
#include <string> using namespace std; /* 验证上面的预备知识 */
template
< typename T, int N > // 这里用成 double 后,编译器显示:error: 'double' is not a valid type for a template constant parameter
void func()
{
T a[N] = {}; for(int i=; i<N; i++)
{
a[i] = i;
} for(int i=; i<N; i++)
{
cout << a[i] << endl;
}
} /* 用最高效的方法验证从 1 加到 n 的和;不用循环和等差数列求和公式 */
template
< int N >
class Sum
{
public:
// static const int VALUE = 0; // static 后是想定义常量,被 static 修饰后要么放入符号表、要么放到全局数据区; 这个时候 VALUE 已经确定了值,所以直接进入符号表(符号表存储在哪里呢);又因为 VALUE 被 static 修饰了,所以 VALUE 被放入全局数据区;
static const int VALUE = Sum<N->::VALUE + N; // 递归定义
}; /* 定义上述模板类的特化实现,实现递归出口 */
template
< >
class Sum < >
{
public:
static const int VALUE = ;
}; int main()
{
func<int, >(); // 打印 0 到 9 这十个数字;这里如果模板参数类型为 double,编译器显示:error: no matching function for call to 'func()'; int a = ;
func<int, a>(); // 在这一行编译器显示:
// error: 'a' cannot appear in a constant-expression
// error: no matching function for call to 'func()' cout << "1 + 2 + 3 + ... + 10 = " << Sum<>::VALUE << endl; // 55;这里没有加减乘除法,也没有函数调用和循环,这里VALUE 是常量,并在编译的时候已经确定,这里效率是最高的;
cout << "1 + 2 + 3 + ... + 100 = " << Sum<>::VALUE << endl; // return ;
}

1,这里的相加求和是在编译器编译程序的时候完成的,编译完程序后,要求的和的值已经确定,在运行的时候,就直接可以访问这个值,不需要做任何的运算和循环,因此效率最高;

2,这个最高效的求和依赖了模板技术、模板特化技术、数值型模板参数技术;

3,可以举一反三,得到更多高效的程序写法;

4,数组模板类编程实验:

1,Array.h 文件:

 #ifndef _ARRAY_H_  // 防止多次包含头文件;
#define _ARRAY_H_ template
< typename T, int N > // 数组元素的类型和大小;
class Array
{
T m_array[N]; // 定义一个实际的数组;
public:
int length();
bool set(int index, T value);
bool get(int index, T& value);
T& operator[] (int index);
T operator[] (int index) const; // 数组类对象有可能是 const 对象,这个时候就只能调用 const 函数,所以要定义这个;const 函数只能返回值,不能返回引用;
virtual ~Array(); // 有可能被继承
}; /* 模板类要放在一个文件中,所以实现在下面实现 */ template
< typename T, int N >
int Array<T, N>::length()
{
return N;
} template
< typename T, int N >
bool Array<T, N>::set(int index, T value)
{
bool ret = ( <= index) && (index < N); if( ret )
{
m_array[index] = value;
} return ret;
} template
< typename T, int N >
bool Array<T, N>::get(int index, T& value)
{
bool ret = ( <= index) && (index < N); if( ret )
{
value = m_array[index];
} return ret;
} template
< typename T, int N >
T& Array<T, N>::operator[] (int index)
{
return m_array[index];
} template
< typename T, int N >
T Array<T, N>::operator[] (int index) const
{
return m_array[index];
} template
< typename T, int N >
Array<T, N>::~Array()
{ } #endif

2,应用:

 #include <iostream>
#include <string>
#include "Array.h" using namespace std; int main()
{
Array<double, > ad; for(int i=; i<ad.length(); i++)
{
ad[i] = i * i;
} for(int i=; i<ad.length(); i++)
{
cout << ad[i] << endl;
} return ;
}

5,堆数组模板类编程实验:

 1,HeapArray.h 文件:

 #ifndef _HEAPARRAY_H_
#define _HEAPARRAY_H_ template
< typename T >
class HeapArray
{
private:
int m_length;
T* m_pointer; HeapArray(int len);
HeapArray(const HeapArray<T>& obj);
bool construct();
public:
static HeapArray<T>* NewInstance(int length);
int length();
bool get(int index, T& value);
bool set(int index ,T value);
T& operator [] (int index);
T operator [] (int index) const; // 有可能有 const 对象;
HeapArray<T>& self();
~HeapArray(); // 这个时候构造函数是 private 的,也就是 HeapArray 类不希望被继承,所以说没有必要将它声明为 virtual 的;
}; /* 实现要在同一个文件中 */ template
< typename T >
HeapArray<T>::HeapArray(int len)
{
m_length = len;
} template
< typename T >
bool HeapArray<T>::construct()
{
m_pointer = new T[m_length]; return m_pointer != NULL;
} template
< typename T >
HeapArray<T>* HeapArray<T>::NewInstance(int length)
{
HeapArray<T>* ret = new HeapArray<T>(length); if( !(ret && ret->construct()) )
{
delete ret;
ret = ;
} return ret;
} template
< typename T >
int HeapArray<T>::length()
{
return m_length;
} template
< typename T >
bool HeapArray<T>::get(int index, T& value)
{
bool ret = ( <= index) && (index < length()); if( ret )
{
value = m_pointer[index];
} return ret;
} template
< typename T >
bool HeapArray<T>::set(int index, T value)
{
bool ret = ( <= index) && (index < length()); if( ret )
{
m_pointer[index] = value;
} return ret;
} template
< typename T >
T& HeapArray<T>::operator [] (int index)
{
return m_pointer[index];
} template
< typename T >
T HeapArray<T>::operator [] (int index) const
{
return m_pointer[index];
} template
< typename T >
HeapArray<T>& HeapArray<T>::self()
{
return *this;
} template
< typename T >
HeapArray<T>::~HeapArray()
{
delete[]m_pointer;
} #endif

2,应用:

 #include <iostream>
#include <string>
#include "HeapArray.h" using namespace std; int main()
{
HeapArray<char>* pai = HeapArray<char>::NewInstance(); if( pai != NULL )
{
HeapArray<char>& ai = pai->self(); for(int i=; i<ai.length(); i++)
{
ai[i] = i + 'a';
} for(int i=; i<ai.length(); i++)
{
cout << ai[i] << endl;
}
} delete pai; return ;
}

6,小结:

1,模板参数可以是数值型参数;

2,数值型模板参数必须在编译期间唯一确定;

3,数组类模板是基于数值型模板参数实现的;

4,数组类模板是简易的线性表数据结构;

C++中的数据类模板的更多相关文章

  1. Sql Server中的数据类型和Mysql中的数据类型的对应关系(转)

    Sql Server中的数据类型和Mysql中的数据类型的对应关系(转):https://blog.csdn.net/lilong329329/article/details/78899477 一.S ...

  2. Xcode6中如何使用自定义的类模板

    说到IOS类的模板,有些人感觉很陌生,但是只要有开发过IOS程序的人,其实都用过类的模板,只不过是用的系统自带的类的模板. 例如创建一个ClassTemplateVC继承于UIViewControll ...

  3. 04737_C++程序设计_第7章_类模板与向量

    例7.1 使用类模板的实例. 例7.2 求4个数中最大值的类模板程序. #include <iostream> using namespace std; template <clas ...

  4. C++_进阶之函数模板_类模板

     C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...

  5. C++复习:函数模板和类模板

    前言 C++提供了函数模板(function template).所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表.这个通用函数就称为函数模板.凡是函数体 ...

  6. C++解析(26):函数模板与类模板

    0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1. ...

  7. 4.1 pair类模板

    在学习关联容器之前,首先先要了解一下STL中的pair类模板,因为关联容器的一些成员函数返回值都是pair对象,而且map 和multimap中的元素都是pair对象. 1)pair类模板定义 pai ...

  8. 类模板的困扰 LNK2019 (转)

    原文地址:http://www.eetop.cn/blog/html/93/493893-14903.html 在使用类模板技术时,可在.h中实现,也可在.h和.cpp中分开实现,若用.h实现,不要在 ...

  9. YTU 2618: B 求类中数据成员的最大值-类模板

    2618: B 求类中数据成员的最大值-类模板 时间限制: 1 Sec  内存限制: 128 MB 提交: 430  解决: 300 题目描述 声明一个类模板,类模板中有三个相同类型的数据成员,有一函 ...

随机推荐

  1. 浏览器使用小tip

    谷歌浏览器截取长图 很多网页长图单个页面截不下来,那么需要如何解决? 首先,在谷歌浏览器chrome中打开需要截图的网页,等待需要截图的网页打开完毕,然后按F12 打开开发者工具,然后按组合键 Ctr ...

  2. JSP中EL表达式不能使用的问题

    在JSP2.0中,增加了EL语言,可以通过EL语言,可以通过EL语言,实现获取数据,进一步将scriptlet 代码从JSP页面中分离出来.EL语言给大家带来了方便,但有时,也会遇到EL表达式不能显示 ...

  3. JavaScript实现页面滚动到div区域div以动画方式出现

    用JavaScript实现页面滚动效果,以及用wow.js二种方式实现网页滚动效果 要实现效果是页面滚动到一块区域,该区域以动画方式出现. 这个效果需要二点: 一:我们要先写好一个css动画. 二:用 ...

  4. nginx负载均衡 理解与测试

    Nginx负载均衡概述 Web服务器,直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台WEB服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后端服务器集群中,实现 ...

  5. postman 测试api接口

    安装:https://www.getpostman.com/ 谷歌插件安装需要翻墙才能访问,那么直接去官网下载pc端 代码图片: 非常简单 post: 代码图片: 剪头地方,必选

  6. EL表达式里面不能直接使用list.size()得到长度,

    在jsp页面中不能通过${list.size}取列表长度, 而是 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" pre ...

  7. linux输出与查看的几种方式

    输出的几种方式:echo/ tee echo "postgres install Failed !!!!!!" | tee -a "$Install_log"# ...

  8. C++入门经典-例6.12-使用数组地址将二维数组输出

    1:以a[4][3]为例 a代表二维数组的地址,通过指针运算符可以获取数组中的元素 (1)a+n代表第n行的首地址 (2)&a[0][0]既可以看作第0行0列的首地址,同样也可以被看作是二维数 ...

  9. 190707Python-Redis

    一.Redis的简单使用 Redis操作模式 # Author:Li Dongfei import redis r = redis.Redis(host='192.168.56.7', port=63 ...

  10. js关闭当前页面(窗口)的几种方式

    1. 不带任何提示关闭窗口的js代码  代码如下: <a href="javascript:window.opener=null;window.open('','_self');win ...