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. Protocol Buffers 开发者指南

    欢迎来到 protocol buffers 的开发者指南.protocol buffers 是一个语言中立,平台中立针对通讯协议,数据存储和其他领域中对结构化数据进行序列化的扩展方法. 本文档主要针对 ...

  2. Selenium 环境安装

    前言: 本人在学习Selenium时,用的版本是Python3.6+Selenium3,后续写的所有学习资料都是基于这套环境.在安装Selenium3前,请确保本机已安装好了Python3,如未安装可 ...

  3. Codeforces Round #201.C-Alice and Bob

    C. Alice and Bob time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  4. conda install -c anaconda

    有些包在conda默认的channels中不包含,比如cudatoolkit-8.0,cudnn等,这时只需要在conda install指令后加上-c anaconda即可.比如要下载cudatoo ...

  5. 黑马lavarel教程---4、csrf验证及相关

    黑马lavarel教程---4.csrf验证及相关 一.总结 一句话总结: csrf验证就像短信验证码那样验证用户身份,这个验证是为了验证是本站的操作,用的是一个token字符串,外站如果有了这个to ...

  6. java基本算法

    1.链表 链表用来存储数据,由一系列的结点组成.这些结点的物理地址不一定是连续的,即可能连续,也可能不连续,但链表里的结点是有序的.一个结点由数据的值和下一个数据的地址组成.一个链表内的数据类型可以是 ...

  7. CAN-FD协议浅析

    引言 随着电子.半导体.通讯等行业的快速发展,汽车电子智能化的诉求也越来越强,消费者希望驾驶动力性.舒适性.经济性以及娱乐性更强的汽车.汽车制造商为了提高产品竞争力,将越来越多的电子控制系统加入到汽车 ...

  8. Tomcat指定JDK

    那么当有多个JDK时,是否可以为Tomcat这类应用程序指定对应的JDK版本 如下图,只需修改catalina.sh 即可,不需要修改“tomcat/bin/setclasspath.sh” . “t ...

  9. [VBA]去重汇总

    问题描述:汇总多个工作表的指定字段到sheet1里面,并去除重复的字段内容. Sub 去重汇总() Dim sht As Worksheet, j As Integer, x As Integer S ...

  10. Linux环境Nginx安装

    开始前,请确认gcc g++开发类库是否装好,默认已经安装. ububtu平台编译环境可以使用以下指令 apt-get install build-essential apt-get install ...