zoukankan      html  css  js  c++  java
  • 第五十九课、类模板的深度剖析

    一、多参数的类模板

    1、类模板可以定义任意多个不同类型的参数

    2、类模板可以被特化

    (1)、指定类模板的特定实现

    (2)、部分类型参数必须显示指定(如class Test<T, T> 就是现实指定T)

    (3)、根据类型参数分开实现类模板(同一个模板根据需要用不同方式来实现而已)

    (4)、类模板的特化类型

    A、部分特化:用特定规则约定类型参数(仍然存在类型参数

    B、完全特化:完全显示指定类型参数

    (5)、特化注意事项

    A、特化只是模板的分开实现(实现的功能都一样,本质上还是同一个模板,根据需要使用不同的实现方式而已)
    B、特化类模板的使用方式是统一的(定义对象时必须显示指定每一个参数的类型

    #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 << endl;
        }
    };
    
    template
    < typename T1, typename T2 >  //部分特化,因为还有类型参数
    class Test < T1*, T2* >      // 关于指针的特化实现,特化时在这里显示指定参数的类型,如这里的< T1*, T2*>
    {               // 用以实现上述模板的特殊情况,本质上还是同一个模板 public: void add(T1* a, T2* b) { cout << "void add(T1* a, T2* b)" << endl; cout << *a + *b << endl; } }; template < typename T >//部分特化 class Test < T, T > // 当 Test 类模板的两个类型参数完全相同时,使用这个实现 { public: void add(T a, T b) { cout << "void add(T a, T b)" << endl; cout << 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; Test<long, long> t2;//选择参数相同的特化类模板 Test<void*, void*> t3;//选择void*时的特化类模板(优先于两个参数相同的那个) t1.add(1, 2.5); t2.add(5, 5); t2.print(); t3.add(NULL, NULL); Test<int*, double*> t4;//选择指针时的版本 int a = 1; double b = 0.1; t4.add(&a, &b); return 0; } //输出结果 /* void add(T1 a, T2 b) 3.5 void add(T a, T b) 10 class Test < T, T > void add(void* a, void* b) Error to add void* param... void add(T1* a, T2* b) 1.1 */

    二、特化与重定义的区别

    1、重定义

    (1)、一个类模板和一个新类(或者两个类模板)

    (2)、使用的时候需要考虑如何选择的问题

    2、特化

    (1)、以统一的方式使用类模板和特化类(定义对象是显示指定参数

    (2)、编译器自动优先选择特化类

    (3)、函数模板的特化(只能完全特化)

    3、工程中的建议

    (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 << 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 << endl;
        }
    };
    
    template
    < typename T >
    class Test < T, T >    // 当 Test 类模板的两个类型参数完全相同时,使用这个实现
    {
    public:
        void add(T a, T b)
        {
            cout << "void add(T a, T b)" << endl;
            cout << 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;
        }
    };
    */

    //类模板的重定义,本质上已经是一个新的类 class Test_void { public: void add(void* a, void* b) { cout << "void add(void* a, void* b)" << endl; cout << "Error to add void* param..." << endl; } };
    /************************ 函数 *******************************/ 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, T double)" << endl; const double delta = 0.00000000000001; double r = a - b; return (-delta < r) && (r < delta); } //函数重定义 bool Equal(double a, double b) { const double delta = 0.00000000000001; double r = a - b; return (-delta < r) && (r < delta); } int main() { //Test<void*, void*> t3; Test_void t3; t3.add(NULL, NULL); cout << endl; cout << Equal<>(1.2, 0.6) << endl;//< > 限定编译器只匹配模板 return 0; }

    四、小结

    (1)、类模板可以定义任意多个类型不同的参数

    (2)、类模板可以被部分特化完全特化

    (3)、特化的本质模板的分开实现

    (4)、函数模板只支持完全特化

    (5)、工程中用模板特化代替类(函数)重定义

  • 相关阅读:
    5.4 省选模拟赛 修改 线段树优化dp 线段树上二分
    一本通 高手训练 1782 分层图 状压dp
    luogu P3830 [SHOI2012]随机树 期望 dp
    5.2 省选模拟赛 或许 线型基
    luogu P4562 [JXOI2018]游戏 组合数学
    一本通 高手训练 1781 死亡之树 状态压缩dp
    luogu P4726 【模板】多项式指数函数 多项式 exp 牛顿迭代 泰勒展开
    4.28 省选模拟赛 负环 倍增 矩阵乘法 dp
    HDU 1756 Cupid's Arrow 计算几何 判断一个点是否在多边形内
    一本通 高手训练 1763 简单树 可持久化线段树 树链刨分 标记永久化
  • 原文地址:https://www.cnblogs.com/gui-lin/p/6376527.html
Copyright © 2011-2022 走看看