59_类模板深度剖析

关键词:多参数类模板、类模板的特化

1. 多参数类模板

  • 类模板可以定义任意多个不同的类型参数
    语法规则:
template 
< typename T1, typename T2 >
class Test
{
public:
    void add(T1 a, T2 b);
};
// Test<int ,float> t;
  • 类模板可以被特化
    (1) 指定类模板的特定实现
    (2) 部分类型参数必须显示指定
    (3) 根据类型参数分开实现类模板

  • 类模板的特化类型

    • 部分特化:用特定规则约束类型参数
    • 完全特化:完全显示指定类型参数


      部分特化

      完全特化

编程说明:类模板的特化

#include <iostream>
#include <string>

using namespace std;

template 
< typename T1, typename T2 >
class Test
{
public:
    void add(T1 a, T2 b)
    {
        cout << "void add(T1 a, T2 b)" << endl;
        cout << "a + b = " << a + b << endl;
    }
};

template 
< typename T1, typename T2 >
class Test < T1*, T2* >
{
public:
    void add(T1* a, T2* b)
    {
        cout << "void add(T1* a, T2* b)" << endl;
        cout << "*a + *b = " << *a + *b << endl;
    }
};

template    
< typename T >              // 部分特化
class Test < T, T >         // Test类模板的特化(特殊实现): 当Test 类模板的两个类型参数完全相同时,使用这个实现
{
public:
    void add(T a, T b)
    {
        cout << "void add(T a, T b)" << endl;
        cout << "a + b = " << a + b << endl;
    }
    void print()
    {
        cout << "class Test < T, T >" << endl;
    }
};

template    
<  >                            // 完全特化
class Test < void*, void* >     // 当 T1 == void*, 且 T2 == void* 时
{
public:
    void add(void* a, void* b)
    {
        cout << "void add(void* a, void* b)" << endl;
        cout << "Error to add void* param... " << endl;
    }
};

int main()
{
    Test<int, float> t1;
    
    t1.add(1, 2.5);
    cout << endl;
    
    Test<long, long> t2;
    
    t2.add(1, 2);
    t2.print();
    cout << endl;
    
    Test<void*, void*> t3;
        
    t3.add(NULL, NULL);
    cout << endl;
    
    Test<int*, double*> t4;
    
    int a = 1;
    double b = 0.1;
    
    t4.add(&a, &b);

    return 0;
}

输出结果

void add(T1 a, T2 b)
a + b = 3.5

void add(T a, T b)
a + b = 3
class Test < T, T >

void add(void* a, void* b)
Error to add void* param... 

void add(T1* a, T2* b)
*a + *b = 1.1

类模板特化注意事项

  • 特化只是模板的分开实现,本质上还是同一个类模板
  • 特化类模板的使用方式是统一的,必须显示指定每一个类型参数

2. 类模板特化与重定义有区别吗?函数模板可以特化吗?

  • 重定义:
    结果:一个类模板和一个新类或者是两个类模板
    使用时:需要考虑如何选择使用哪一个的问题
  • 特化:
    结果:以统一的方式使用类模板和特化类
    使用时:编译器自动优先选择特化类

编程说明:重定义与特化

#include <iostream>
#include <string>

using namespace std;

template 
< typename T1, typename T2 >
class Test
{
public:
    void add(T1 a, T2 b)
    {
        cout << "void add(T1 a, T2 b)" << endl;
        cout << "a + b = " << a + b << endl;
    }
};

class Test_Void
{
public:
    void add(void* a, void* b)      // 重定义
    {
        cout << "Test_Void::void add(void* a, void* b)" << endl;
        cout << "Error to add void* param..." << endl;
    }
};

template 
<  >
class Test< void*, void* >          // 特化
{
public:
    void add(void* a, void* b)
    {
        cout << "Test< void*, void* >::void add(T1 a, T2 b)" << endl;
        cout << "Error to add void* param..." << endl;
    }
};

int main()
{
    Test_Void t1;   
    Test<void*, void*> t2;
    double a = 1.2;
    int b = 1;
    void* m = &a;
    void* n = &b;
    
    t1.add(m, n);
    cout << endl;
    
    t2.add(m, n);

    return 0;
}

输出结果

Test_Void::void add(void* a, void* b)
Error to add void* param...

Test< void*, void* >::void add(T1 a, T2 b)
Error to add void* param...

总结:能用特化时优先考虑使用特化,而不是重定义

函数模板只支持类型参数完全特化

编程说明:函数模板的完全特化

#include <iostream>
#include <string>

using namespace std;

template 
<typename T>
bool Equal(T a, T b)
{
    cout << "bool Equal(T a, T b)" << endl;
    return a = b;
}

template                        //  函数模板的完全特化
< >
bool Equal(double a, double b)  
{
    cout << "bool Equal(double a, double b)" << endl;
    double delta = 0.00000000000001;
    double r = a - b;
    
    return (-delta < r) && (r < delta);
}

int main()
{
    cout << Equal(1, 1) << endl;
    cout << Equal(0.001, 0.001) << endl;

    return 0;
}

输出结果

bool Equal(T a, T b)
1
bool Equal(double a, double b)
1

工程中的建议:当需要重载函数模板时,优先考虑使用模板特化;当模板特化无法满足需求时,再使用函数重载

3. 小结

  • 类模板可以定义任意多个不同的类型参数
  • 类模板可以被部分特化完全特化
  • 特化的本质是模板的分开实现
  • 函数模板只支持完全特化
  • 工程中使用模板特化代替类(函数)重定义
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容