C++学习7-模板

模板:
优点:对类型也可以参数化了
01函数模板 02类模板

tmplate<>  定义一个模板参数列表 --》可以定义模板参数

模板参数:
1.类型参数 — typename /class 定义多个类型参数 用,号分隔
2.非类型参数 — int a(默认是个常量 不可以被修改)

函数模板/类模板
函数或者类前面有template

template<typename T> // 模板参数列表
class vector()
此处的vector是模板名称,不能直接使用,需要实例化才能使用,在实现vector模板的成员方法时使用vector的地方都要加上<T> 只有构造函数和析构函数的名字可以省略<T>

在类外定义模板方法时,需要加上类的作用域,是vector:: 参数T需要重新定义

模板函数/模板类
是实例化以后的

1.模板不编译 编译的是实例化后的模板
模板中使用的类型替换是使用 typedef

template<typename T> // 模板参数列表
bool compare(T a, T b)
{
    cout << typeid(T).name() << endl;
    cout << "compare template" << endl;
    return a > b;
}
int main()
{
    //bool __cdecl compare<int>(int,int);
    // 在函数调用点, 用int从模板实例化一份代码
    // 模板的隐式实例化
    compare<int>(10, 20.5);
    compare<int>(20, 30);
}

以下是系统自己根据传入的类型参数实例化出的模板函数:

/*
模板函数
bool compare<int>(int a, int b)
{
    cout << "compare template" << endl;
    return a > b;
}
bool compare<double>(double a, double b)
{
    cout << "compare template" << endl;
    return a > b;
}
bool compare<const char*>(const char* a, const char* b)
{
    cout << "compare template" << endl;
    return a > b;
}
*/

2.模板的实参推演 编译器可以根据传入的实参类型,推导出来形参类型T

template<typename T> // 模板参数列表
bool compare(T a, T b)
{
    cout << typeid(T).name() << endl;
    cout << "compare template" << endl;
    return a > b;
}
int main()
{
    // const char *
    // 模板的实参推演
    compare("aaa", "bbb");
虽然没有传入类型 但是模板会根据实参"aaa"推演出该用const char 类型(字符串是常量)

bool compare<const char*>(const char* a, const char* b)
{
    cout << "compare template" << endl;
    return a > b;
}

但是这里return a>b;比较字符串的地址 这是错误的,所以有时候编译器自己推出来的会出错,需要特例化一下!
注意:模板只是省了开发者的活,但是没有省编译器的活.编译器仍然会自动实例化模板函数

3.针对以上问题,我们要自己实例化一个模板函数,这就叫做针对char*类型的特例化函数(本来是编译器自己实例化的)

template<>//括号里空着是因为是特例化所以已经知道调什么类型 就不写了
bool compare<const char*>(const char*a, const char*b)
{
    cout << "compare<const char*>" << endl;
    return strcmp(a, b) > 0;//按照字母的前后顺序比较
}

ps:
模板和特例化必须保持模板名相同,参数形式形同
模板会在调用地方实例化出来对应的函数或者类
模板内的成员方法如果没有被使用也不会被编译
模板的实例化在编译期
4.写成如下代码,优先理解为函数名,然后才是模板

compare("aaa", "bbb");

写成如下代码,优先理解为模板,然后才是函数名

compare<const char*>("aaa", "bbb");

5.模板的代码不能定义在源文件中,然后在另外的源文件中调用,它都是放在头文件中,源文件用#include导出来(可以导头文件)
因为:模板代码不进行编译 不产生符号(如果模板的代码不在这个调用的源文件里,那就只是无符号的,那就没法用)

   // compare<int>  *UND*
    // compare *UND*
    // compare<const char*> *UND*

解决方法:
tip1: 模板的显示实例化
(没什么意思,只是在模板所在的源文件先实例化了要用的类型,然后就生成了符号,从而在调用点的源文件里找的时候就能找到)

template<typename T> // 模板参数列表
bool compare(T a, T b)
{
    cout << typeid(T).name() << endl;
    cout << "compare template" << endl;
    return a > b;
}


// 模板的显示实例化
template bool compare<int>(int, int);

tip2: 模板的隐式实例化
(大多用的是这个方法,就是都在一个源文件/模板在头文件里,不知道实例化过没,没的话就给他实例化)

template<typename T> // 模板参数列表
bool compare(const T a, const T b)
{
    cout << typeid(T).name() << endl;
    cout << "compare template" << endl;
    return a > b;
}

......
    compare<int>(10, 20.5);
    compare<int>(20, 30);

6.模板的特例化必须在函数名 函数的参数形式上保持一致
函数的原模板和特例化模板必须在同一作用域
对于模板中使用的类型替换使用typedef

template <typename T>
class Test{
public:
    void print(){
        cout << "General template object" << endl;
    }
};
template<>   // 对int型特例化
class Test<int>{
public:
    void print(){
        cout << "Specialized template object" << endl;
    }
};
int main()
{
    Test<int> a;
    Test<char> b;
    Test<float> c;
    a.print();
    b.print();
    c.print();
    return 0;
}

输出结果:

Specialized template object
General template object
General template object

7.参数匹配都以最佳匹配为原则。

特例化的本质是实例化一个模板,而非重载它。特例化不影响参数匹配。
例如,下面如果是compare(3,5),则调用普通的模板,若为compare(“hi”,”haha”)则调用特例化版本(因为这个cosnt char*相对于T,更匹配实参类型),注意,二者函数体的语句不一样了,实现不同功能。

template<typename T> //函数模板
int compare(const T &v1,const T &v2)
{
    if(v1 > v2) return -1;
    if(v2 > v1) return 1;
    return 0;
}
//模板特例化,满足针对字符串特定的比较,要提供所有实参,这里只有一个T
template<>
int compare(const char* const &v1,const char* const &v2)
{
    return strcmp(p1,p2);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值