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. BZOJ 3589: 动态树 树链剖分+线段树+树链的并

    利用树剖序的一些性质~ 这个题可以出到 $\sum k=10^5$ 左右. 做法很简单:每次暴力跳重链,并在线段树上查询链和. 查询之后打一个标记,把加过的链都置为 $0$.这样的话在同一次询问时即使 ...

  2. javascript中继承方式及优缺点(二)

    一.原型链继承 方式1: 原型链继承 (1)流程: ​ 1.定义父类型构造函数. ​ 2.给父类型的原型添加方法. ​ 3.定义子类型的构造函数. ​ 4.创建父类型的对象赋值给子类型的原型. ​ 5 ...

  3. 使用git将代码上传到GitHub

    使用git将代码上传到GitHub   结束了前一段的时间的杂七杂八的生活,最近又快开始动一动已经吃了好长时间土的GitHub,以前的git指令基本上忘个差不多,现在记录一下,利用git将代码上传. ...

  4. python学习之路(5)

    条件判断 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现: age=20 if age>=18: ...

  5. sqli-labs(5)

    双查询注入 0x01爱之初了解 在第一次接触到双查询注入时 肯定会有很多问题 在这里我们先了解一下什么叫做 双查询注入 他的语法结构 以及为什么这样构造 答:在此之前,我们理解一下子查询,查询的关键字 ...

  6. 7、kubernetes资源清单之Service资源190714

    一.Service简介 Service为Pod提供固定服务端点 Service的本质是一条iptables或者ipvs的转发规则 userspace:1.1- iptables:1.1+ ipvs:1 ...

  7. 第11组 Beta冲刺(2/5)

    第11组 Beta冲刺(2/5) 队名 不知道叫什么团队 组长博客 https://www.cnblogs.com/xxylac/p/11997386.html 作业博客 https://edu.cn ...

  8. Scala学习(四)——模式匹配与函数组合

    函数组合 让我们创建两个函数: def f(s: String) = "f(" + s + ")" def g(s: String) = "g(&qu ...

  9. SpringBoot启动加载yml配置文件出现编码格式错误

    Caused by: org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input l ...

  10. Laravel框架之获取URL地址

    1. 使用 Request 类: $url = Request::getRequestUri(); 2. 使用 $request 对象: public function show(Request $r ...