目录
一模板函数
1 一般模板函数
1.1代码实现
template <class T>
int compare(const T& left, const T& right)
{
if (left < right) return -1;
else if (left > right) return 1;
else return 0;
}
template <class T,int size>
int compare(T(&v1)[size], T(&v2)[size])
{
for (int i = 0; i <= size;i++)
{
if (v1[i] > v2[i]) return 1;
else if (v1[i] < v2[i]) return -1;
}
return 0;
}
int main(int argc, char** argv) {
cout<< compare(1, 2)<<endl;
cout << compare(2.5,3.6)<<endl;
cout << compare("aab","aac")<<endl;
const char* a = "aab";
const char* b = "aaa";
cout << compare(a, b);
}
1.2 运行截图
1.3 小结
显然我们可以用该一般模板函数进行大部分同类型数值的比较,template <class T>
用于单个数据,而template <class T,int size>
用于数组,但当类型为const char*时通过该函数简单的< > =是无法对这种特殊类型数值大小进行正确比较,所以大部分类型比较用一般模板函数即可,而特殊的类型比较应该用特化模板函数。
2 特化模板函数
2.1 代码实现
#include < iostream>
#include <stdio.h>
#include<malloc.h>
#include "CMatrix.h"
using namespace std;
template <class T>
int compare(const T& left, const T& right)
{
if (left < right) return -1;
else if (left > right) return 1;
else return 0;
}
template <class T,int size>
int compare(T(&v1)[size], T(&v2)[size])
{
for (int i = 0; i <= size;i++)
{
if (v1[i] > v2[i]) return 1;
else if (v1[i] < v2[i]) return -1;
}
return 0;
}
template < >
int compare<const char*>(const char* const& v1, const char* const& v2)
{
return strcmp(v1, v2);
}
int main(int argc, char** argv) {
cout<< compare(1, 2)<<endl;
cout << compare(2.5,3.6)<<endl;
cout << compare("aab","aac")<<endl;
const char* a = "aab";
const char* b = "aaa";
cout << compare(a, b);
}
2.2 运行截图
2.3 小结
template<class T>
int compare(const T& left, const T& right)
template <class T,int size>
int compare(T(&v1)[size], T(&v2)[size])
template < >
int compare<const char*>(const char* const& v1, const char* const& v2)
{
return strcmp(v1, v2);
}
3个compare的模板函数已经可以比较好的解决绝大部分数据的正确比较。
二 模板类Queue或Stack
1 模板类
1.1 代码实现
queue.h文件:
#ifndef QUEUE_H
#define QUEUE_H
#include <iostream>
using namespace std;
//定义类模板
template<class Type> class Queue;
template<class Type> class QueueItem {
QueueItem(const Type& t) : item(t), next(0) {}
Type item;
QueueItem* next;
friend class Queue<Type>;
//输出运算符的重载
friend ostream& operator<<(ostream& os, const Queue<Type>& q);
QueueItem<Type>* operator++() {
return next;
}
Type& operator*() {
return item;
}
};
template<class Type> class Queue {
public:
Queue() : head(0), tail(0) {}
Queue(const Queue& q) : head(0), tail(0) {
copy_items(q);
}
//成员函数模板
template <class It>
Queue(It beg, It end) : head(0), tail(0) { copy_items(beg, end); }
template<class It> void assign(It beg, It end);
Queue& operator=(const Queue&);
//析构函数
~Queue() { destroy(); }
Type& front() { return head -> item; }
const Type& front() const { return head -> item; }
//元素入队
void push(const Type&);
//队尾元素出队
void pop();
bool empty() const { return head == 0; }
//输出符重载(第二个参数表示待输出的队列)
//(全局)友元函数
friend ostream& operator<<(ostream& os, const Queue<Type>& q) {
os << "< ";
QueueItem<Type>* p;
for (p = q.head; p; p = p -> next) {
os << p->item << " ";
}
os << ">";
return os;
}
const QueueItem<Type>* Head() const { return head; }
const QueueItem<Type>* End() const { return (tail == NULL) ? NULL : tail -> next; }
private:
QueueItem<Type>* head;
QueueItem<Type> *tail;
void destroy();
void copy_items(const Queue&);
template<class It>
void copy_items(It beg, It end);
};
template<class Type>
void Queue<Type>::pop() {
QueueItem<Type>* p = head;
head = head -> next;
delete p;
}
template<class Type>
void Queue<Type>::push(const Type& val) {
QueueItem<Type>* pt = new QueueItem<Type>(val);
if (empty()) {
head = tail = pt;
}
else {
tail -> next = pt;
//元素添加到队列后tail指针指向该元素
tail = pt;
}
}
template < >
void Queue<const char*>::push(const char* const& val);
template < >
void Queue<const char*>::pop();
template <class Type>
void Queue<Type>::copy_items(const Queue& orig) {
for (QueueItem<Type>* pt = orig.head; pt; pt = pt -> next) {
push(pt -> item);
}
}
template <class Type>
Queue<Type>& Queue<Type>::operator=(const Queue& q)
{
destroy();
copy_items(q);
}
template<class Type> template<class It> void Queue<Type>::assign(It beg, It end)
{
destroy();
copy_items(beg, end);
}
template<class Type> template<class It> void Queue<Type>::copy_items(It beg, It end)
{
while (beg != end) {
push(*beg);
++beg;
}
}
//销毁队列
template<class Type>
void Queue<Type>::destroy()
{
while (!empty()) {
pop();
}
}
void TestQueue();
#endif
main.cpp文件:
#include<iostream>
#include "queue.h"
using namespace std;
int main() {
Queue<int> qt;
qt.push(8);
qt.push(6);
qt.push(2);
cout << qt;
return 0;
}
1.2运行截图
1.3 小结
类模板的使用能使用户为类定义一种模式,使得类中的某些数据出成员、某些成员函数的参数、返回值或局部变量能取不同类型(包括系统预定义的和用户自定义的),使一些类灵活性和通用性更高。
2 成员模板函数
2.1代码实现
实现代码
//成员模板函数的实现
template <class It>
Queue(It beg, It end) : head(0), tail(0) { copy_items(beg, end);
}
//成员模板函数的实现
template<class Type>
template<class It>
void Queue<Type>::copy_items(It beg, It end)
{
while (beg != end) {
//将数组中下标对应的值添加到队列中
push(*beg);
++beg;
}
}
测试代码
int a[5] = { 1,2,3,4,5 };
Queue<int> q(a,a+5);
cout << q;
2.2运行截图
2.3 小结
通过成员模板函数让该类的适用性更强,让类中的一个函数可以处理多种类型参数变量。
3 模板特化
3.1 代码实现
具体实现
template <>
void Queue<const char*>::push(const char* const& val) {
char* new_item = new char[strlen(val) + 1];
//将val的值赋值到new_item,其中strlen(val)为需要复制的长度
strncpy_s(new_item,strlen(new_item),val, strlen(val));
QueueItem<const char*>* pt = new QueueItem<const char*>(new_item);
if (empty()) {
head = tail = pt;
}
else {
tail->next = pt;
tail = pt;
}
}
template <>
void Queue<const char*>::pop() {
QueueItem<const char*>* p = head;
delete head->item;
head = head->next;
delete p;
}
测试代码
Queue<const char*> q1;
q1.push("www");
q1.push("hhc");
q1.push("6666");
cout << q1;
3.2 运行截图
3.3 小结
特殊类型可以调用模板特化函数来实现一般模板不能实现的效果。
三 模板类AutoPtr
1 代码实现
具体实现
#ifndef AUTOPTR_H
#define AUTOPTR_H
template <class T>
class AutoPtr
{
public:
//构造函数
AutoPtr(T* pData);
//拷贝构造函数
AutoPtr(const AutoPtr<T>& h);
//声明周期结束时调用析构函数
~AutoPtr();
//等号的重载
AutoPtr<T>& operator=(const AutoPtr<T>& h);
//用户数减1
void decrUser();
//指针运算符重载(返回的指针允许被改变)
T* operator ->() {
return m_pData;
}
//返回一个对象(能使用成员运算符(".")来访问成员变量)
T& operator*() {
return *m_pData;
}
const T& operator *() const {
return *m_pData;
}
//指针运算符重载(返回的指针不允许被改变)
const T* operator -> () const {
return m_pData;
}
private:
//存储数据
T* m_pData;
//存储用户数
int* m_nUser;
};
template < class T>
AutoPtr<T>::AutoPtr(T* pData)
{
m_pData = pData;
//初始化用户数为1
m_nUser = new int(1);
}
template < class T>
AutoPtr<T>::AutoPtr(const AutoPtr<T>& h) {
m_pData = h.m_pData;
m_nUser = h.m_nUser;
//用户数加1
(*m_nUser)++;
}
template < class T>
AutoPtr<T>& AutoPtr<T>::operator=(const AutoPtr<T>& h)
{
decrUser();
m_pData = h.m_pData;
m_nUser = h.m_nUser;
(*m_nUser)++;
}
template < class T>
void AutoPtr<T>::decrUser()
{
--(*m_nUser);
if ((*m_nUser) == 0) {
//删除数据
delete m_pData;
//地址赋为空
m_pData = 0;
delete m_nUser;
m_nUser = 0;
}
}
template < class T>
AutoPtr<T>::~AutoPtr()
{
decrUser();
}
#endif // AUTOPTR_H
测试代码
AutoPtr<CMatrix> h1(new CMatrix);
double data[10] = { 1,2,3,4,5,6,7,8,9,10 };
//生成一个2行5列的数组
h1->Create(2, 5, data);
cout << *h1 << endl;
//h2(拷贝构造函数的使用)和h1指向的是同一个地方
AutoPtr<CMatrix> h2(h1);
(*h2).Set(0, 1, 10);
cout << *h1 << *h2 << endl;
2 运行截图
3 小结
AutoPtr类似于Java中对象管理机制的智能指针类,它能够实时监测对象的用户数量,并控制其生命周期的结束(当对象的用户数为0时释放该对象所占用的内存)。