C++的函数加尖括号<>:函数模板、类模板

一、函数模板

1、问题引入

        很多C/C++初学者们在刷各种笔试题或者看项目工程代码的时候,或多或少遇到过下面这样的问题。就是为什么一个函数调用时,能够在函数中间加上一个尖括号<>,到底是干嘛用的?

        

        当然可能是会有以下的一些困扰,所以去去思考如何去优化函数重载时重复类型的代码:

void _swap(int &a,int &b)  //定义函数的时候不能直接使用swap 这个名字是 标准C++库的接口
{
    a = a+b;b=a-b;a=a-b;
}
void _swap(double &a,double &b)
{
    a = a+b;b=a-b;a=a-b;
}
void _swap(char &a,char &b)
{
    a = a+b;b=a-b;a=a-b;
}

函数的重载可以实现一个函数名多用,将实现相同的或类似功能的函数用一个函数名来定义。这种使用在程序中仍然需要定义每一个函数,用不同的形参类型来实现多态。那么,如何实现只需要定义一个函数,能够适应不同类型的形参实现多态呢??使用函数模板

2、概念

所谓的函数模板[拼音:mú bǎn],实际上就是建立一个通用函数,其函数返回值类型和形参类型不具体指定, 用一个虚拟的类型来代表。这个通用函数就称为函数模版 。

模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。

template<typename T>
void _swap(T &a, T &b) //注意:函数名不要使用swap ,这是系统接口
{
    cout<<T swap<<endl;
    a = a+b;b=a-b;a=a-b;
}

3、函数模板格式

template<typename T>  或 template<class T>
T 模板函数名(T a)
{
}

T 是函数所使用的数据类型的占位符名称,这个名称可以在函数定义中使用。

class和typename的作用相同,都是表示“类型名”,二者可以互换。

在建立函数模版时,只要将第一个函数用虚拟的类型名T代替具体的数据类型。在对程序进行编译时,遇到模版函数的调用,编译系统会将函数名与模版相匹配,将实参的类型取代函数模版中的虚拟类型T

每一个函数模板都要定义自己的虚拟模板类型,不同函数的虚拟模板类型可以一样,但是不是能省略

template<typename T>
T show(T a){cout<<a<<endl;}
template<typename T> //此处不能省略
T print(T a){cout<<a<<endl;}

模板参数必须全部确定为具体类型才能生成模板函数,可以设置默认数据类型参数

template<typename T,typename Ty=int>
void print(T a)
{
    cout<<a<<endl;
}

调用的时候可以显式指定数据类型

print<int>(10);

4、例子

#include<iostream>

//表示下面这个函数时一个通用函数(函数模板),并且声明T 是一个虚拟的数据类型 int、double、char
template  <typename T>
void swapFunc(T &ra, T &rb)
{
    ra = ra + rb;
    rb = ra - rb;
    ra = ra - rb;
}

template <typename T1, typename T2>
void func1(T1 &ra, T2 &rb)
{
    (void)ra;
    (void)rb;
    std::cout<<"func(T1 &ra, T2 &rb)"<<std::endl;

}

int main(int argc, char **argv)
{
    int num1 = 20;
    int num2 = 30;
    std::cout<<"函数模板"<<std::endl;
    std::cout<<"num="<<num1<<"\tnum2="<<num2<<std::endl;
    swapFunc<int>(num1, num2);    //<int>指明 template  <typename T>中的T在此处是int类型
    std::cout<<"num="<<num1<<"\tnum2="<<num2<<std::endl;
    int num3 = 10;
    double num4 = 20.1;
    func1<int,double>(num3, num4);

    return 0;
}

二、类模板

1、问题引入

现在要实现两个数的一系列运算,比如比较大小

//浮点型比较类
class CompareA{
public:
    CompareA(double a,double b):x(a),y(b){}
    double max(){return x>y?x:y;}
    double min(){return x<y?x:y;}
private:
    double x,y;
};
//整型比较类
class CompareB{
public:
    CompareB(int a,int b):x(a),y(b){}
    int max(){return x>y?x:y;}
    int min(){return x<y?x:y;}
private:
    int x,y;
};

上面两个类除了数据类型不一样,其他功能都一样,此时可以使用类模板简化成同一个类。

#include <iostream>
using namespace std;
//类模板
template<class T=int>
class Compare{
public:
    Compare(T a,T b):x(a),y(b){}
    T max();//{return x>y?x:y;} //类内声明
    T min(){return x<y?x:y;}
private:
    T x,y;
};
//类外定义,T的默认参数不需要加
template<class T>
T Compare<T>::max()
{
    return x>y?x:y;
}
int main()
{
    //调用的时候显示指定具体的数据类型
    Compare<double> mya(10,200);
    //如果是使用默认的,那么<>括号也不能省略,里面可以为空
    //Compare<> mya(10,200);
    cout<<mya.max()<<endl;
    cout<<mya.min()<<endl;
    return 0;
}

2、格式

template<class T>
class 类名{

};

       总结:T表示的是数据类型

3、模板类继承

#include <iostream>
using namespace std;

//模板类--基类
template<class T>
class Base{
public:
    Base(T n):baseA(n){}
private:
    T baseA;
};


//设计一个子类Child 继承模板类Base<T> -->子类Child也是模板类
template<class T>
class Child:public Base<T>{
public:
    Child(T n):Base<T>(n){}
private:
    T childA;
};
//设计一个子类Data 继承模板类Base<T> -->子类Data是具体类
class Data:public Base<int>{
public:
    Data(int n):Base<int>(n){}
private:
    int DataA;
};
int main()
{
    Child<int> mya(10);
    Data myb(10);
    return 0;
}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值