C++中的数据类模板

1,预备知识:

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

1,代码示例:

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

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

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

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

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

1,浮点数本身不精确;

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

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

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

2,有趣的面试题:

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

1,等差数列和的方式;

2,见下面实例;

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

 1 #include <iostream>
 2 #include <string>
 3
 4 using namespace std;
 5
 6 /* 验证上面的预备知识 */
 7 template
 8 < typename T, int N >  // 这里用成 double 后,编译器显示:error: ‘double‘ is not a valid type for a template constant parameter
 9 void func()
10 {
11     T a[N] = {0};
12
13     for(int i=0; i<N; i++)
14     {
15         a[i] = i;
16     }
17
18     for(int i=0; i<N; i++)
19     {
20         cout << a[i] << endl;
21     }
22 }
23
24 /* 用最高效的方法验证从 1 加到 n 的和;不用循环和等差数列求和公式 */
25 template
26 < int N >
27 class Sum
28 {
29 public:
30     // static const int VALUE = 0;  // static 后是想定义常量,被 static 修饰后要么放入符号表、要么放到全局数据区; 这个时候 VALUE 已经确定了值,所以直接进入符号表(符号表存储在哪里呢);又因为 VALUE 被 static 修饰了,所以 VALUE 被放入全局数据区;
31     static const int VALUE = Sum<N-1>::VALUE + N;  // 递归定义
32 };
33
34 /* 定义上述模板类的特化实现,实现递归出口 */
35 template
36 < >
37 class Sum < 1 >
38 {
39 public:
40     static const int VALUE = 1;
41 };
42
43 int main()
44 {
45     func<int, 10>();  // 打印 0 到 9 这十个数字;这里如果模板参数类型为 double,编译器显示:error: no matching function for call to ‘func()‘;
46
47     int a = 10;
48     func<int, a>();  // 在这一行编译器显示:
49        // error: ‘a‘ cannot appear in a constant-expression
50        // error: no matching function for call to ‘func()‘
51
52     cout << "1 + 2 + 3 + ... + 10 = " << Sum<10>::VALUE << endl;  // 55;这里没有加减乘除法,也没有函数调用和循环,这里VALUE 是常量,并在编译的时候已经确定,这里效率是最高的;
53     cout << "1 + 2 + 3 + ... + 100 = " << Sum<100>::VALUE << endl;   // 5050
54
55     return 0;
56 }    

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

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

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

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

1,Array.h 文件:

 1 #ifndef _ARRAY_H_  // 防止多次包含头文件;
 2 #define _ARRAY_H_
 3
 4 template
 5 < typename T, int N >  // 数组元素的类型和大小;
 6 class Array
 7 {
 8     T m_array[N];  // 定义一个实际的数组;
 9 public:
10     int length();
11     bool set(int index, T value);
12     bool get(int index, T& value);
13     T& operator[] (int index);
14     T operator[] (int index) const;  // 数组类对象有可能是 const 对象,这个时候就只能调用 const 函数,所以要定义这个;const 函数只能返回值,不能返回引用;
15     virtual ~Array();  // 有可能被继承
16 };
17
18 /* 模板类要放在一个文件中,所以实现在下面实现 */
19
20 template
21 < typename T, int N >
22 int Array<T, N>::length()
23 {
24     return N;
25 }
26
27 template
28 < typename T, int N >
29 bool Array<T, N>::set(int index, T value)
30 {
31     bool ret = (0 <= index) && (index < N);
32
33     if( ret )
34     {
35         m_array[index] = value;
36     }
37
38     return ret;
39 }
40
41 template
42 < typename T, int N >
43 bool Array<T, N>::get(int index, T& value)
44 {
45     bool ret = (0 <= index) && (index < N);
46
47     if( ret )
48     {
49         value = m_array[index];
50     }
51
52     return ret;
53 }
54
55 template
56 < typename T, int N >
57 T& Array<T, N>::operator[] (int index)
58 {
59     return m_array[index];
60 }
61
62 template
63 < typename T, int N >
64 T Array<T, N>::operator[] (int index) const
65 {
66     return m_array[index];
67 }
68
69 template
70 < typename T, int N >
71 Array<T, N>::~Array()
72 {
73
74 }
75
76 #endif

2,应用:

 1 #include <iostream>
 2 #include <string>
 3 #include "Array.h"
 4
 5 using namespace std;
 6
 7 int main()
 8 {
 9     Array<double, 5> ad;
10
11     for(int i=0; i<ad.length(); i++)
12     {
13         ad[i] = i * i;
14     }
15
16     for(int i=0; i<ad.length(); i++)
17     {
18         cout << ad[i] << endl;
19     }
20
21     return 0;
22 }

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

 1,HeapArray.h 文件:

  1 #ifndef _HEAPARRAY_H_
  2 #define _HEAPARRAY_H_
  3
  4 template
  5 < typename T >
  6 class HeapArray
  7 {
  8 private:
  9     int m_length;
 10     T* m_pointer;
 11
 12     HeapArray(int len);
 13     HeapArray(const HeapArray<T>& obj);
 14     bool construct();
 15 public:
 16     static HeapArray<T>* NewInstance(int length);
 17     int length();
 18     bool get(int index, T& value);
 19     bool set(int index ,T value);
 20     T& operator [] (int index);
 21     T operator [] (int index) const;  // 有可能有 const 对象;
 22     HeapArray<T>& self();
 23     ~HeapArray();  // 这个时候构造函数是 private 的,也就是 HeapArray 类不希望被继承,所以说没有必要将它声明为 virtual 的;
 24 };
 25
 26 /* 实现要在同一个文件中 */
 27
 28 template
 29 < typename T >
 30 HeapArray<T>::HeapArray(int len)
 31 {
 32     m_length = len;
 33 }
 34
 35 template
 36 < typename T >
 37 bool HeapArray<T>::construct()
 38 {
 39     m_pointer = new T[m_length];
 40
 41     return m_pointer != NULL;
 42 }
 43
 44 template
 45 < typename T >
 46 HeapArray<T>* HeapArray<T>::NewInstance(int length)
 47 {
 48     HeapArray<T>* ret = new HeapArray<T>(length);
 49
 50     if( !(ret && ret->construct()) )
 51     {
 52         delete ret;
 53         ret = 0;
 54     }
 55
 56     return ret;
 57 }
 58
 59 template
 60 < typename T >
 61 int HeapArray<T>::length()
 62 {
 63     return m_length;
 64 }
 65
 66 template
 67 < typename T >
 68 bool HeapArray<T>::get(int index, T& value)
 69 {
 70     bool ret = (0 <= index) && (index < length());
 71
 72     if( ret )
 73     {
 74         value = m_pointer[index];
 75     }
 76
 77     return ret;
 78 }
 79
 80 template
 81 < typename T >
 82 bool HeapArray<T>::set(int index, T value)
 83 {
 84     bool ret = (0 <= index) && (index < length());
 85
 86     if( ret )
 87     {
 88         m_pointer[index] = value;
 89     }
 90
 91     return ret;
 92 }
 93
 94 template
 95 < typename T >
 96 T& HeapArray<T>::operator [] (int index)
 97 {
 98     return m_pointer[index];
 99 }
100
101 template
102 < typename T >
103 T HeapArray<T>::operator [] (int index) const
104 {
105     return m_pointer[index];
106 }
107
108 template
109 < typename T >
110 HeapArray<T>& HeapArray<T>::self()
111 {
112     return *this;
113 }
114
115 template
116 < typename T >
117 HeapArray<T>::~HeapArray()
118 {
119     delete[]m_pointer;
120 }
121
122 #endif

2,应用:

 1 #include <iostream>
 2 #include <string>
 3 #include "HeapArray.h"
 4
 5 using namespace std;
 6
 7 int main()
 8 {
 9     HeapArray<char>* pai = HeapArray<char>::NewInstance(10);
10
11     if( pai != NULL )
12     {
13         HeapArray<char>& ai = pai->self();
14
15         for(int i=0; i<ai.length(); i++)
16         {
17             ai[i] = i + ‘a‘;
18         }
19
20         for(int i=0; i<ai.length(); i++)
21         {
22             cout << ai[i] << endl;
23         }
24     }
25
26     delete pai;
27
28     return 0;
29 }

6,小结:

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

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

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

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

原文地址:https://www.cnblogs.com/dishengAndziyu/p/10919050.html

时间: 2024-10-09 00:45:21

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

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

Sql Server中的数据类型和Mysql中的数据类型的对应关系(转):https://blog.csdn.net/lilong329329/article/details/78899477 一.SQL SERVER与MySQL数据存储的差异 1.SQL SERVER中的datetime,保留到微秒(秒后小数点3位),而mysql仅保留到秒,转换后是否会影响业务,如果影响,需要新增一个字段专门来存储微秒或者毫秒,虽然mysql中没有时间数据类型的精度到达微秒或者毫秒,但是mysql提供对微秒的

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

说到IOS类的模板,有些人感觉很陌生,但是只要有开发过IOS程序的人,其实都用过类的模板,只不过是用的系统自带的类的模板. 例如创建一个ClassTemplateVC继承于UIViewController 创建出来的ClassTemplateVC如下: #import "ClassTemplateVC.h" @interface () @end @implementation ClassTemplateVC - (void)viewDidLoad { [super viewDidLoa

泛函编程—模板函数_类模板

函数业务逻辑一样,只是函数参数类型不同函数模板的本质:类型参数化——泛型编程 语法: template <typename T> template <class T1,class T2>多个参数类型 类型 函数名(形式参数表) { 语句序列: } 函数模板基础: template是告诉C++编译器,开始泛型编程,看到T,不要随便报错 template <typename T>//一个模板 void myswap(T& a, T& b) { T c; c

类模板的友元

详见http://www.cnblogs.com/assemble8086/archive/2011/10/02/2198308.html 类模板的友元有三种声明: 1)非模板类的友元类或友元函数 1 template <typename T> 2 class Rect{ 3 public: 4 friend void create(); 5 }; create函数成为所有Rect类实例化的友元,它可以访问全局对象;可以使用全局指针访问非全局对象;可以创建自己的对象;可以访问独立对象的模板类的

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

0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1.函数模板 1.1 函数模板与泛型编程 C++中有几种交换变量的方法? 交换变量的方法--定义宏代码块 vs 定义函数: 定义宏代码块 优点:代码复用,适合所有的类型 缺点:编译器不知道宏的存在,缺少类型检查 定义函数 优点:真正的函数调用,编译器对类型进行检查 缺点:根据类型重复定义函数,无法代码复

类模板的概念和意义

思考:在C++中是否能够将泛型的思想应用于类? 类模板 一些类主要用于存储和组织数据元素 类中数据组织的方式和数据元素的具体类型无关 如:数组类,链表类,Stack类,Queue类,等 C++中将模板的思想应用于类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能. C++中的类模板 以相同的方式处理不同的类型 在类声明前使用template进行标识 <typename T>用于说明类中使用的泛指类型T template <typename T> { public:

C++程序设计_第7章_类模板与向量

例7.1 使用类模板的实例. 例7.2 求4个数中最大值的类模板程序. 1 #include <iostream> 2 3 using namespace std; 4 5 template <class T> 6 7 class Max4 8 { 9 T a, b, c, d; 10 T Max(T a, T b) 11 { 12 return (a > b) ? a : b; 13 } 14 public: 15 Max4(T, T, T, T); 16 T Max(vo

c++类模板深度剖析

1.类模板的泛指类型可以定义多个 template <typename T1, typename T2> class Test { public: void add(T1 a, T2, b); }; 使用时: Test<int, float> t1; //T1的泛指类型就是int, T2的泛指类型就是float. 2.类模板的特化类型 (1)意思就是如果定义了一个类模板,这个类模板的参数有多个,但是如果当使用这个类模板的时候,我们传递参数时,参数的类型是一样的话,编译器就会将类模板

4.1 pair类模板

在学习关联容器之前,首先先要了解一下STL中的pair类模板,因为关联容器的一些成员函数返回值都是pair对象,而且map 和multimap中的元素都是pair对象. 1)pair类模板定义 pair实例化出来以后的类都有两个成员变量,一个是first,另一个是second. STL中还有一个make_pair()函数模板,可以返回一个pair模板对象.源码如下: template<class T1, class T2> pair<T1,T2>make_pair(T1 x, T2