C++-提高篇-1-模板

1-模板

00x1 模板的概念

模板就是建立通用的模具,提高代码的复用性

特点:

  • 模板不可以直接使用,它只是一个框架
  • 模板的通用并不是万能的

00x2 函数模板

C++另一种编程思想称为泛型编程,主要利用的技术就是模板

学习模板不是为了写模板,而是为了运用STL

C++提供两种模板机制:函数模板和类模板

模板函数

建立一个通用函数,其函数返回值类型和形参类型可以不具体指定,用一个虚拟的类型来代表

template<typename T>  
函数声明或定义

//template:声明创建模板
//typename:数据类型。可以用class代替
//T:通用的数据类型,名称可以替换,通常为大写字母

定义:

//函数模板的定义
template<typename T>
void mySwap(T &a, T &b)
{
    T temp = a;
    a = b;
    b = temp;
}

使用:

//1、自动推断
mySwap(a,b);
//2、指定类型
mySwap<int>(a,b); //int用于替换T

注意事项:

//1、自动类型推导必须推导出一致的类型
template<typename T>
void swap(T &a, T &b)
{
    T temp = a;
    a = b;
    b = temp;
}
int a=10,b=20;
char c='A';
mySwap(a,c);    //错误
mySwap(a,b);   //正确
//2、模板必须要确定T的数据类型,才可以使用
template<typename T>
void func()
{
    std::cout<<"func"<<std::endl;
}
//func()并没有使用T,调用时编译器报错
func();
//可以把<T>补上,尽管没用
func<int>();

main()函数中不允许声明模板

普通函数与模板函数的区别

  • 普通函数可以实现隐式转换
  • 模板函数的自动类型推导不能实现隐式类型转换
  • 模板函数的指定类型可以实现隐式转换
//举个例子
//普通函数
int Add(int a,int b)
{
    return a+b;
}

//模板函数
template<typename T>
T TAdd(T a,T b)
{
    return a+b;
}

int a = 10, b= 20;
char c = 'a';

//对于普通函数来说,c只是一个常数
Add(a,b);    //正确
Add(a,c);    //也正确

//但对于模板函数而言,自动推断时c是char
TAdd(a,b);    //正确
TAdd(a,c);    //错误

//指定类型则可以实现类型转换
TAdd(a,b);    //正确
TAdd(a,c);    //也正确

尽量直接指定类型,不要偷懒!

调用规则:

//1、如果普通函数和模板函数都可以调用,则优先调用普通函数
//普通函数
void func(int a,int b)
{
    cout<<"普通函数"<<endl;
}
//模板函数
template<typename T>
void func(T a,T b)
{
    cout<<"模板函数"<<endl;
}
//重载模板函数
template<typename T>
void func(T a,T b,T c)
{
    cout<<"重载模板函数"<<endl;
}
int main()
{
    using namespace std;
    int a = 10,b =20,c=30;
    char d = 'a',e = 'b';
    func(a,b);    //输出“普通函数”
    //func<>(a,b);    //输出“模板函数”
    func(a,b,c);    //输出“重载模板函数”
    func(d,e);    //输出“模板函数”
}   

//如果注释普通函数的实现,则报错,编译器不会自动选择模板函数

//2、可以通过空模板参数列表,强制调用模板函数,如上

//3、模板函数可以发生重载,编译器按参数数量自动选择模板函数

//4、如果模板函数有更好的匹配,优先调用模板函数

局限性

//模板并不是万能
template<typename T>
void func(T a,T b)
{
    a = b;    //如果a或b是数组,则出错
}

T也不可以是自定义类型,但可以解决

//1、运算符重载
//2、具体化自定义函数
template<>
bool myCopare(person &p1,person &p2)
{
    ...
}

00x3 类模板

template<class nameType,class ageType>    //自定义类型nameType和ageType
class person
{
    public:
        person(nameType name,ageType age)
        {
            this->m_name=name;    //类的成员变量m_name赋值
            this->m_age=age;    //类的成员变量m_age赋值
        }
    void showInfo()
    {
        cout << "age = " << this->m_age << "name = " << this->name <<endl;
    }
    nameType m_name;
    ageType m_age;
};

int main()
{
    person<string,int>p1("小张",24);  //实例化对象
    p1.showInfo();
    return 0;
}

类模板与函数模板的区别

  • 类模板中的模板参数列表可以有默认参数
  • 类模板使用只能显式指定类型方式

类模板中成员函数创建时机

  • 普通类中的成员函数一开始就可以创建
  • 类模板中的成员函数在调用时才创建
class Person1
{
public:
	void showPerson()
	{
		cout << "Person1 show" << endl;
	}
};

template <class T>
class MyClass
{
public:
	T obj;
	void func()
	{
		obj.showPerson1();    //调用showPerson()
	}
};

//类模板中的函数只有被调用时才创建,因此 编译 的时候这段代码没有任何问题

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex·Leace

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值