模板

如何实现一个通用的函数呢?(如针对不同的参数类型均可)

在平时的编程中,如何实现一个通用的函数呢?

首先想到的就是使用函数重载,但是这样一来会有几个不好的地方:

  1. 重载的函数仅仅只是类型不同,代码的复用率比较低,只要有新类型出现时就需要增加对应的函数
  2. 代码可维护率比较低,一个函数出错就有可能所有的重载都出错

那么有没有一种方式,使得编译器可以根据不同的类型来利用该模子来生成代码呢?

答案是有的——泛型编程,也就是一种编写与类型无关,与使用场景无关的通用代码,使得代码可以复用的手段,而模板则是泛型编程的基础

模板:

模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。

  1. 模板是一种对类型进行参数化的工具;
  2. 通常有两种形式:函数模板类模板
  3. 函数模板针对仅参数类型不同的函数
  4. 类模板针对仅数据成员成员函数类型不同的类。

使用模板的目的就是能够让程序员编写与类型无关的代码。比如编写了一个交换两个整型int 类型的swap函数,这个函数就只能实现int 型,对double,字符这些类型无法实现,要实现这些类型的交换就要重新编写另一个swap函数。使用模板的目的就是要让这程序的实现与类型无关,比如一个swap模板函数,即可以实现int 型,又可以实现double型的交换。模板可以应用于函数和类。下面分别介绍。

注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。

函数模板

是一个函数家族,与类型无关,使用时才被参数化,根据实参类型产生函数的适用版本

函数模板格式

template<class T1,class T2> //模板参数列表 可以使用template ,不可以使用struct

T1 _Add(T1 left,T2 right) //函数模板

{

​ return left + right;

}

实例化:
隐式实例化:

编译器根据实参推演模板参数的实际类型

显示实例化:

函数名和后加<>指定参数实际类型

匹配原则:

1.优先调用自己写的模板函数

2.模板函数不允许自动类型转换,普通函数可以自动类型转换

#pragma once
#include<assert.h>
#include<iostream>
using namespace std;


//不是一个真正的函数
template<class T>     //模板参数列表 可以使用template<typename T> ,不可以使用struct 
T _Add(T left,T right)       //函数模板
{
	return left + right;
}

template<class T>
void PrintfArray(T array,int size)  //数组会自己转换类型
{
	cout<<typeid(array).name() <<endl;
	int i = 0;
	for(i=0;i<size;i++)
	{
		cout<< array[i] << " ";
		cout<<endl;
	}

}

int main()
{
	int array[] = {1,2,3,4,};
	char str[] = "hello";
	PrintfArray(array,sizeof(array)/sizeof(int));
	PrintfArray(str,strlen(str));
	//隐式实例化---不会进行隐式的类型转化,需要用户自己来强转/
	cout<< _Add(1,2) <<endl;   //根据实参类型来进行类型推演生成处理具体类型的函数
	cout<< _Add(1,(int)2.0) <<endl;  //但是面对参数为不同类型时无法判断如何输出,需要对参数进行处理,如强转类型

	//显式实例化
	_Add<int>(1,2.2);
	_Add<>(1,2);    //隐式实例化
	return 0;
}

用模板写list类

template<class T>
class Seqlist
{
public:
	Seqlist(int capacity = 10)
		:_Data(new T[capacity])
		,_capacity(capacity)
		,_size(0)
	{}

	//拷贝构造:Seqlist(const Seqlist<T>& s);
	//赋值运算符重载:Seqlist<T>& operator = (const Seqlist<T>& s)

	void PushBack(const T& data)
	{
		_CheckCapacity();
		_Data[_size++] = data;
	}

	void PopBack()
	{
		if(_size != 0)
			--_size;
	}

	//访问任意位置
	T& operator[](size_t index)               //可能会修改s[i]中的元素
	{
		assert(index < _size);
		return _Data[index];
	}

	//因为const类型的对象不能调用普通函数,这里是const对象访问
	const T& operator[](size_t index) const
	{
		assert(index < _size);
		return _Data[index];
	}

	//访问第一个元素
	T& Front()
	{
		return _Data[0];
	}

	const T& Front()const
	{
		return _Data[0];
	}

	//访问最后一个元素
	T& Back()
	{
		return _Data[_size-1];
	}

	const T& Back()const
	{
		return _Data[_size-1];
	}

	size_t Size() const
	{
		return _size;
	}

	size_t Capacity() const
	{
		return _capacity;
	}

	void Clear()
	{
		_size = 0;
	}

	~Seqlist();
private:
	void _CheckCapacity()
	{
		if(_size == _capacity)
		{
			size_t newCapacity = (_capacity<<1);
			//申请空间
			T* Temp = new T[newCapacity];
			//拷贝元素
			memcpy(Temp,_Data,_size*sizeof(T));
			//释放旧空间
			delete[] _Data;
			//替换新空间
			_Data = Temp;
			_capacity = newCapacity;
		}
	}
private:
	T* _Data;
	size_t _capacity;
	size_t _size;
};

template<class T>
Seqlist<T>::~Seqlist()
{
	if(_Data)
	{
		delete[] _Data;
		_Data = nullptr;
		_capacity = 0;
		_size = 0;
	}
}

void TestSeqlist()
{
	Seqlist<int> s1;   
	Seqlist<double> s2;
	Seqlist<char> s3;

	s1.PushBack(1);
	s1.PushBack(2);
	s1.PushBack(3);
	s1.PushBack(4);
	s1[0] = 6;
	cout<< s1.Size()<<endl;
	cout<< s1.Front()<<endl;
	cout<< s1.Back()<<endl;
	s1.Clear();
	cout<<s1.Size()<<endl;
}

#include<string>
void Test()
{
	Seqlist<string> s;
	s.PushBack("0000");
	s.PushBack("1111");
	s.PushBack("2222");
	s.PushBack("3333");
	s.PushBack("4444");
	s.PushBack("5555");
	s.PushBack("6666");
	s.PushBack("7777");
	s.PushBack("8888");
	s.PushBack("9999");
}
int main()
{
	//TestSeqlist();
	Test();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值