• c++函数模板,类模板以使用



    前言:泛型编程,大家应该都听过,c++是支持泛型编程的,C语言不支持,泛型编程的实现离不开模板。模板由函数模板,类模板组成。
    在这里插入图片描述


    1.函数模板

    函数模板代表了一个函数家族,它可以被实例化成具体的函数,但必须是使用时被参数化,根据参数而实例成具体的函数。
    比如交换函数,我可能要交换的数据是整型,浮点型,字符型等等,要是C语言我们就需要写对应的版本,但是c++支持泛型编程,我们来用一个函数模板就能在使用时实例化成对应的交换函数版本。

    (1) 函数模板的格式

    template
    返回值类型 函数名(参数列表)
    {}

    (2) 交换函数的函数模板
    template<typename T>
    void Swap( T& x, T& y)
    {
     T temp = x;
     x = y;
     y = temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    (3) 通过调试 交换函数 ,理解函数模板原理
    #include
    using namespace std;
    template<typename T>
    void Swap(T& left, T& right)
    {
    	T temp = left;
    	left = right;
    	right = temp;
    }
    int main()
    {
    	//整型
    	int a = 1; int b = 2;
    	Swap(a, b);
    	//浮点型
    	float x = 1.1; float y = 2.2;
    	Swap(x, y);
    	//字符型
    	char i = 'a'; char u = 'b';
    	Swap(i, u);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    首先,Swap(a,b),整型的交换。
    在这里插入图片描述
    进入Swap函数后,可以看到left,right的类型是整型,进行整型交换,
    在这里插入图片描述
    再来看Swap(x,y),交换浮点型数据,
    在这里插入图片描述
    最后交换字符型数据,
    在这里插入图片描述
    分析:可以看到,在进行传参时,根据传参的不同,函数也会实例化成相应的函数,具体可看上面调试中left,right的变化,传int型时,left,right为int;传float时,left和right为float;传char时,left和right为char。
    具体关系如下图:
    在这里插入图片描述
    也就是说,函数模板可以根据传参来自动推演成相应的函数。
    当然,如果不想让函数模板去推演,也可以自己显示的实例化,

    Swap<类型>(a,b);
    
    • 1
    (4) 模板参数的匹配机制

    上文中,Swap函数只能匹配同类型的数据交换,如果交换int和char就会出错,
    如下:

    //混合型交换
    int m = 10; char w='Q';
    Swap(m, w);
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    原因很简单,函数模板中只有一个参数T,这表明传来的参数必须是相同的类型,否则就会实例化失败。
    解决方案:模板中再给一个参数T1,两个不同参数,所以可以有俩种类型。

    template<typename T,typename T1>
    void Swap(T& left, T1& right)
    {
    	T temp = left;
    	left = right;
    	right = temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    那么可以想到,如果传的参数是三种类型,那么必须有三个模板参数去对应。
    还有一种情况,假如Swap函数有专门处理整型类型数据转换的,会不会去调用模板去实例化呢?还是说根本就不会实例化,直接去调用专门的函数呢?
    我们可以实验一下:

    void Swap(int& x, int& y)
    {
    	int temp = x;
    	x = y;
    	y = temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    调试来看一看:
    在这里插入图片描述
    小黄标指在专门的函数上,说明它去调用专门的对应函数了。
    结论:
    对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板(这种情况说明那个函数还不够专门)。


    2. 类模板

    类模板就是,c++中的类中成员需要支持泛型,也就是类的成员可能根据需求类型会发生改变。

    (1) 类模板的格式
    template<class T1, class T2, ..., class Tn>
    class 类模板名
    {
     // 类内成员定义
    }; 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    举一个例子:类模板A可以创建包含不同类型的数组,数组包含_a个元素。

    template<class T>
    class A
    {
    public:
    	A(int a = 1)
    	{
    		_a = a;
    		ptr = new T[_a];
    	}
    	~A()
    	{
    		delete[] ptr;
    		ptr = nullptr;
    		_a = 0;
    	}
    private:
    	int _a;
    	T* ptr;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    可以看到,这个类模板A就实现了这样的功能,可以根据需求,包含不同类型的数组,具体类型不是靠传参,不能像函数模板那样去推演,只能显示的实例化类模板。

    (2) 类模板的使用
    #include
    using namespace std;
    template<class T>
    class A
    {
    public:
    	A(int a = 1)
    	{
    		_a = a;
    		ptr = new T[_a];
    	}
    	~A()
    	{
    		delete[] ptr;
    		ptr = nullptr;
    		_a = 0;
    	}
    private:
    	int _a;
    	T* ptr;
    };
    int main()
    {
    	A<int> m(3);
    	A<double>w(4);
    	A<char>E(5);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    模板类和普通的类不同:

    • 普通的类:类名+对象名就可以了,类名就是类。
    • 模板类:类名<类型> +对象名才行,并且类名<类型>才是类。

    通过调试带大家看一看。
    在这里插入图片描述
    可以清楚看到,int*,double*,char*,根据需求开辟了不同类型的数组。
    还需要强调一点:类模板中函数放在类外进行定义时,需要加模板参数列表。

    template <class T>
    A<T>::~A()
    {
      delete[] ptr;
      ptr = nullptr;
      _a = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结尾语:以上是模板的基础应用,对于高级用法后面会更新的。

  • 相关阅读:
    MD文档中插入数学公式,Typora中插入数学公式
    LR学习笔记——图片管理分类
    安防视频监控系统EasyCVR视频汇聚存储平台定制化开发:新增kafka配置
    流量5-----5
    22 行为型模式-状态模式
    2022年最火的十大测试工具,你掌握了几个
    ACM第三周总结
    ZJU Beamer学习手册(二)
    取消task异步任务
    有效保护敏感数据的最佳实践
  • 原文地址:https://blog.csdn.net/lyzzs222/article/details/126432401