C++ 重点知识梳理(五) --------- 泛指类型

本文探讨了泛型编程的优缺点,对比了模板函数与普通函数,详细解析了模板的全特化和偏特化,以及它们在C++编程中的应用。

六、泛型编程

6.1 使用模板的优点和缺点?

优点:

  1. 在一些场景可以避免重复代码
  2. 有些问题难以使用OO技巧(如继承和多态)来实现,而使用模版会很方便
  3. template classes更加的类型安全,因其参数类型在编译时都是已知的。

缺点:

  1. 一些编译器对template支持不好。
  2. 编译器给出的有些出错信息比较晦涩。
  3. 为每种类型都生成额外的代码,可能导致生成的exe膨胀。
  4. 使用templates写的代码难以调试
  5. templates在头文件中,这样一旦有所变更需要重编译所有相关工程

6.2 模板函数和函数的对比?

  1. 模板函数由函数模板实例化而来,编译器推断模板实参,然后实例化出对应的函数定义。模板函数是函数模板的实例。
  2. 普通函数需要程序员手动重载才能实现对于不同类型参数的支持。
  3. 函数模板只能用于函数的参数个数相同而类型不同的情况,如果参数个数不同,则不能使用函数模板,只能使用重载。
  4. 函数模板必须要求所有实参的类型T都相同,无法进行隐式类型转换。
  5. 进行函数调用时,编译器优先选择匹配的非模板函数,如果找不到再试着进行函数模板的实例化,如果还不行,则这个调用违法。这样做可以减少函数模板实例化次数,提高效率。

6.3 模板的全特化和偏特化?

什么是特化?

所谓特化,就是将泛型的东东搞得具体化一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰(例如const或者摇身一变成为了指针之类的东东,甚至是经过别的模板类包装之后的模板类型)或完全被指定了下来。

 

模板有两种特化,全特化和偏特化(局部特化) 模板函数只能全特化,没有偏特化(以后可能有)。 模板类是可以全特化和偏特化的。 全特化,就是模板中模板参数全被指定为确定的类型。 全特化也就是定义了一个全新的类型,全特化的类中的函数可以与模板类不一样。 偏特化,就是模板中的模板参数没有被全部确定,需要编译器在编译时进行确定。 在类型上加上const、&、*( cosnt int、int&、int*、等等)并没有产生新的类型。只是类型被修饰了。模板在编译时,可以得到这些修饰信息。

模板为什么要特化,因为编译器认为,对于特定的类型,如果你能对某一功能更好的实现,那么就该听你的。

模板分为类模板与函数模板,特化分为全特化与偏特化。全特化就是限定死模板实现的具体类型,偏特化就是如果这个模板有多个类型,那么只限定其中的一部分。

先看类模板:

template<typename T1, typename T2>  
class Test  
{  
public:  
    Test(T1 i,T2 j):a(i),b(j){cout<<"模板类"<<endl;}  
private:  
    T1 a;  
    T2 b;  
};  
  
template<>  
class Test<int , char>  
{  
public:  
    Test(int i, char j):a(i),b(j){cout<<"全特化"<<endl;}  
private:  
    int a;  
    char b;  
};  
  
template <typename T2>  
class Test<char, T2>  
{  
public:  
    Test(char i, T2 j):a(i),b(j){cout<<"偏特化"<<endl;}  
private:  
    char a;  
    T2 b;  
}; 

 那么下面3句依次调用类模板、全特化与偏特化:

Test<double , double> t1(0.1,0.2);  
Test<int , char> t2(1,'A');  
Test<char, bool> t3('A',true);

 而对于函数模板,却只有全特化,不能偏特化: 

//模板函数  
template<typename T1, typename T2>  
void fun(T1 a , T2 b)  
{  
    cout<<"模板函数"<<endl;  
}  
  
//全特化  
template<>  
void fun<int ,char >(int a, char b)  
{  
    cout<<"全特化"<<endl;  
}  
  
//函数不存在偏特化:下面的代码是错误的  
/* 
template<typename T2> 
void fun<char,T2>(char a, T2 b) 
{ 
    cout<<"偏特化"<<endl; 
} 
*/ 

 

注意:

  • 至于为什么函数不能偏特化,似乎不是因为语言实现不了,而是因为偏特化的功能可以通过函数的重载完成。
  • 函数模版的全特化不参与函数重载, 并且优先级低于函数基础模版参与匹配,也就是说,匹配的顺序是:

1. 非模板函数

2. 某个没有进行全特化的template function

3. 如果这个没有进行全特化的template function有全特化版本,并且类型也比较匹配,则选择这个全特化版本

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值