C++入门篇5---模板

相信大家都遇到过这么一种情况,为了满足不同类型的需求,我们要写多个功能相同,参数类型不同的代码,为此,C++引入了泛型编程这一概念,而模板就是实现泛型编程的基础,其实本质就是我们写一个类似"模板"的代码,当遇到不同类型需求时,编辑器会按照我们写的模板,自动生成对应类型的函数或类,来防止相似的代码写很多遍的情况。

举个例子,假设我们要写一个交换函数

cpp 复制代码
//以前
void Swap(int& x,int& y){
    int tmp=x;
    x=y;
    y=tmp;
}

//....将类型换成我们需要的类型


//现在
//函数模板
template<class T>
void Swap(T& x,T& y){
    T tmp=x;
    x=y;
    y=tmp;
}

一、函数模板

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本

函数模板格式

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表){}

注意:这里class和typename都可以,template的作用有点像typedef,这里特别提醒一点,每写一个函数模板或类模板,都要单独写一个template<>

下面写一个加法函数模板

cpp 复制代码
template<class T>
T Add(const T& x, const T& y)
{
    return x + y;
}

int main()
{
    cout << Add(1, 2) << endl;
    cout << Add(1.1, 2.2) << endl;
    return 0;
}

底层实现:编辑器根据传的参数,自动推导类型,然后根据模板实例化函数,然后运行得出答案

函数模板的实例化---显式实例化和隐式实例化

上面的代码就是隐式实例化,即类型是编辑器自动推导的 ,不是我们给的,但是当参数的类型不同时( 如Add(1,1.2) ),编辑器就会出现问题,因为T可能是int,也可能是double

这时我们有两种选择

1.强转,将两个类型统一,这样隐式实例化就能成立

2.显式实例化,直接用Add<int>表明T的类型,不用编辑器自动推动,

注意:如果有多个<class T1,class T2,...,class Tn>要根据顺序对应着写类型

代码如下

cpp 复制代码
template<class T>
T Add(const T& x, const T& y)
{
    return x + y;
}
int main()
{
    //强转
    cout << Add(1, (int)1.2) << endl;
    cout << Add((double)1, 1.2) << endl;
    //显示类型转换
    cout << Add<int>(1, 1.2) << endl;
    cout << Add<double>(1,1.2) << endl;
    return 0;
}

当函数模板和实体函数同时存在时,如果不显示调用,编辑器会默认调用已经存在的实体函数,如下

函数模板的匹配原则

1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数

2. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

3. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

二、类模板

类模板格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};

类模板的实例化

举个例子

cpp 复制代码
template<class T>
class Vector
{
private:
    T* _a;
    size_t _size;
    size_t _capacity;
public:
    Vector(size_t n = 4)
        :_a(new T[n])
        ,_size(0)
        ,_capacity(n)
    {}

    //void push(T x);
    //...

    ~Vector();
};

template<class T>
Vector<T>::~Vector()//在类外写定义要加类型名,即类名+<>,而在正常类中,类型名==类名
{
    delete[] _a;
    _size = _capacity = 0;
}


int main()
{
    Vector<int>s1;//必须显式实例化
    Vector<double>s2;
    return 0;
}
相关推荐
nice_lcj52013 分钟前
深入理解 Java 反射:从 Class 对象到方法调用(含性能实测 + 迷你 IOC 实战 + 面试考点)
java·开发语言·后端·面试
樱花树下的数学喵2 小时前
手写简易 STL string|C++ 字符串底层实现
开发语言·c++
AI吃大瓜2 小时前
指针压力表读数3:C/C++实现指针压力表读数(可实时检测)
c++·指针读数·指针压力表·压力表自动读数·压力表读数
-银雾鸢尾-2 小时前
两数之和-C++实现
c++·算法
j7~2 小时前
【动态规划算法专题】动态规划五部曲实战:泰波那契数、三步问题、最小花费爬楼梯
c++·算法·动态规划·数据结构与算法
jimy12 小时前
C++ 报错的 qualifiers 的意思
开发语言·c++
揽星河..3 小时前
【C++】类和对象
c++·算法
D e re k ZH4 小时前
C++ 并发、未定义行为与工程化难点(No 3)
数据结构·c++·算法·面试
不积跬步无以至千里mmbb264 小时前
rust_analysis
开发语言·后端·rust
暴力求解5 小时前
C++ ---继承(二)
开发语言·c++·算法