C++中的数据类模板
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++中的数据类模板的更多相关文章
- Sql Server中的数据类型和Mysql中的数据类型的对应关系(转)
Sql Server中的数据类型和Mysql中的数据类型的对应关系(转):https://blog.csdn.net/lilong329329/article/details/78899477 一.S ...
- Xcode6中如何使用自定义的类模板
说到IOS类的模板,有些人感觉很陌生,但是只要有开发过IOS程序的人,其实都用过类的模板,只不过是用的系统自带的类的模板. 例如创建一个ClassTemplateVC继承于UIViewControll ...
- 04737_C++程序设计_第7章_类模板与向量
例7.1 使用类模板的实例. 例7.2 求4个数中最大值的类模板程序. #include <iostream> using namespace std; template <clas ...
- C++_进阶之函数模板_类模板
C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...
- C++复习:函数模板和类模板
前言 C++提供了函数模板(function template).所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表.这个通用函数就称为函数模板.凡是函数体 ...
- C++解析(26):函数模板与类模板
0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1. ...
- 4.1 pair类模板
在学习关联容器之前,首先先要了解一下STL中的pair类模板,因为关联容器的一些成员函数返回值都是pair对象,而且map 和multimap中的元素都是pair对象. 1)pair类模板定义 pai ...
- 类模板的困扰 LNK2019 (转)
原文地址:http://www.eetop.cn/blog/html/93/493893-14903.html 在使用类模板技术时,可在.h中实现,也可在.h和.cpp中分开实现,若用.h实现,不要在 ...
- YTU 2618: B 求类中数据成员的最大值-类模板
2618: B 求类中数据成员的最大值-类模板 时间限制: 1 Sec 内存限制: 128 MB 提交: 430 解决: 300 题目描述 声明一个类模板,类模板中有三个相同类型的数据成员,有一函 ...
随机推荐
- BZOJ 3589: 动态树 树链剖分+线段树+树链的并
利用树剖序的一些性质~ 这个题可以出到 $\sum k=10^5$ 左右. 做法很简单:每次暴力跳重链,并在线段树上查询链和. 查询之后打一个标记,把加过的链都置为 $0$.这样的话在同一次询问时即使 ...
- javascript中继承方式及优缺点(二)
一.原型链继承 方式1: 原型链继承 (1)流程: 1.定义父类型构造函数. 2.给父类型的原型添加方法. 3.定义子类型的构造函数. 4.创建父类型的对象赋值给子类型的原型. 5 ...
- 使用git将代码上传到GitHub
使用git将代码上传到GitHub 结束了前一段的时间的杂七杂八的生活,最近又快开始动一动已经吃了好长时间土的GitHub,以前的git指令基本上忘个差不多,现在记录一下,利用git将代码上传. ...
- python学习之路(5)
条件判断 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现: age=20 if age>=18: ...
- sqli-labs(5)
双查询注入 0x01爱之初了解 在第一次接触到双查询注入时 肯定会有很多问题 在这里我们先了解一下什么叫做 双查询注入 他的语法结构 以及为什么这样构造 答:在此之前,我们理解一下子查询,查询的关键字 ...
- 7、kubernetes资源清单之Service资源190714
一.Service简介 Service为Pod提供固定服务端点 Service的本质是一条iptables或者ipvs的转发规则 userspace:1.1- iptables:1.1+ ipvs:1 ...
- 第11组 Beta冲刺(2/5)
第11组 Beta冲刺(2/5) 队名 不知道叫什么团队 组长博客 https://www.cnblogs.com/xxylac/p/11997386.html 作业博客 https://edu.cn ...
- Scala学习(四)——模式匹配与函数组合
函数组合 让我们创建两个函数: def f(s: String) = "f(" + s + ")" def g(s: String) = "g(&qu ...
- SpringBoot启动加载yml配置文件出现编码格式错误
Caused by: org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input l ...
- Laravel框架之获取URL地址
1. 使用 Request 类: $url = Request::getRequestUri(); 2. 使用 $request 对象: public function show(Request $r ...