• 类模板、函数模板及其特化


    (1) -------------类模板 体验--------------------

    template <typename T1, typename T2>
    class Test //原始的类模板后 加上class Test<T1, T2>会报错
    {
    public:
    void add(T1 a, T1 b)
    {
    cout << "void add(T1 a, T1 b)" << endl;
    cout << "a + b = " << a+b << endl;
    }
    };

    template <typename T1, typename T2>
    class Test<T1*, T2*> // class Test<T1, 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, typename T_again> 这是不被编译器允许的。泛指类型T_again没有被使用,会引起编译报错。
    template <typename T>
    class Test<T, T>
    {
    public:
    void add(T a, T b)
    {
    cout << "void add(T a, T b) "<< endl;
    cout << "a + b = " << a+b << endl;
    }
    };
    /* 这个模板类和上面的这个本质是同一个模板类。
    template <typename T2>
    class Test<T2, T2>
    {
    public:
    void add(T2 a, T2 b)
    {
    cout << "void add(T a, T b) "<< endl;
    cout << "a + b = " << a+b << 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 myClass{
    }; // 编译器默认提供的构造函数是公有的。

    int main(void)
    {
    int x = 12;
    unsigned int y = 13;

    Test<int ,int> a;
    a.add(3, 6);

    Test<int*, unsigned int*> b;
    b.add(&x, &y);

    Test < void*, void* > c;
    c.add((void*)&x, (void*)&y);

    myClass mytest;

    return 0;
    }

     

    (2)-------  模板类的特化 ------------------------------------- 

    template
    <typename T1, typename T2, typename T3>
    class Test{
    public:
    T3 get_add(T1 a, T2 b)
    {
    T3 tmp = a+b;
    cout<< "原始的 类模板 Test: get_add = "<< tmp << endl;

    return tmp;
    }
    };


    template
    <typename T1, typename T2>
    //class Test<T1, T2>{ // ????? 编译报错 原因: 既然命名为Test,
    // 那么编译器肯定认为这是上面那个类的特化实现,所以报错 缺少参数(上面那个类是三个参数的哦)
    class Test2{ // 把这里改为Test2以后,编译器认为这个类和上面的Test类没有关系了,这是一个新的类模板,自然也不会报错缺少参数之类的了。
    public:
    void get_add(T1 a, T2 b)
    {
    cout<< "这是重新定义了一个新的类模板哦!不是特化!" endl;
    }
    };


    template
    <typename T1, typename T2>
    class Test<T1, T2, int>{ //由于只指定了一部分参数,剩下的未指定的需在参数列表中,否则编译会报错。
    //class Test2{
    public:
    int get_add(T1 a, T2 b)
    {
    int tmp = a + b;
    cout<< "部分特化的类模板 Test: get_add = "<< a+b << endl;
    return tmp;
    }
    };

     

    template<>
    //class Test<void*, void*, int>{ // ******* 喜发现,如果这里是void*,那么下面传入int*,即定义Test<int*,int*,int> obj_3;,并不能顺利匹配,会引起编译报错。
    class Test<int*, int*, int>{
    public:
    int get_add(int* p1, int*p2) // main函数内调用该类对象的该成员函数进行二次编译的时候,
    { // 报错 class Test<T1, T2, int>的该部分特化的类模板的成员函数不能进行两个指针的相加。
    int tmp = static_cast<int>( *(int*)p1 + *(int*)p2 ); // 所以我在想,难道同一个类模板的部分特化的优先级高于完全特化? 实测NO
    cout<< "完全特化的类模板 " ; // 编译器按照部分特化的类的规则,去对我写的完全特化的类,进行编译检查了
    // 如果这里是void* 去匹配传入int*, 是有问题的。因为这俩不是同一个类型啊!  所以说,特化遵循严格的类型匹配!
    return tmp; // 我们平常习惯了默认提供的的隐式类型转换,这是个毛病。void*和int*不是同一个类型。
    }
    };


    template<>
    class Test<int, int, int>{
    public:
    int get_add(int a, int b)
    {
    int tmp = a + b;
    cout<< "3个int的 完全特化的类模板 Test: get_add = "<< a+b << endl;
    return tmp;
    }
    };

    int main()
    {
    // 范型之--- 类模板 部分特化 完全特化 实验

    // int 同类型相加
    Test<int, int, int> obj;
    int result = obj.get_add(2, 3);
    cout << "result = "<< result << endl<< endl;

    // float 同类型相加
    Test<float, float, float> obj_1;
    float result_1 = obj_1.get_add(2.333, 3.3);
    cout << "result_1 = "<< result_1 << endl<< endl;

    // int float 混合类型相加
    Test<int, float, float> obj_2;
    float result_2 = obj_2.get_add(2.333, 3.4);
    cout << "result_2 = "<< result_2 << endl<< endl;

    // 指针类型相加
    Test<int*,int*,int> obj_3;

    int x1=22; int x2 = 33;
    int result_3 = obj_3.get_add(&x1, &x2);

    cout << "result_3 = "<< result_3 << endl;

    return 0;
    }
    // 类名很重要,是不是同一个类模板,要看是不是同一个类名。
    // 类模板有特化,同一个类模板的类之间,类名肯定都是一样的。
    // 类模板的成员函数的实参到形参的传递,int*到void*需要手动去显式转换才ok。 实测是如此。
    // int 和 double之类的隐式转换也是类似的。
    // 一般的我们认为void*兼容int*之类的。
    // 可是在类模板的这个实验里,体现出了的确存在类型不同的问题。
    // 用习惯了编译器平时的隐式转换咯!是个毛病。

     

    (3)--------------------------函数模板 : 函数模板只有完全特化----------------------------------

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

    return a == b;
    }

    // 上述函数模板的一种特化实现
    template <>
    bool Equal(int a, int b)
    {
    cout << "bool Equal(int a, int b)"<< endl;
    return a == b;
    }

    /* 突发奇想? 想写个函数模板的部分特化?哈哈,想一想,在main函数内该如何定义生成使用这部分特化的函数模板呢?
    template <typename T, char b>
    bool Equal(int a, int b)
    {
    cout << "函数模板部分特化"<< endl; // 函数模板的特化,只有完全特化!
    return a == b;
    }
    */

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

    return 0;
    }

     

    .

    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    第3章 管道符、重定向与环境变量
    基于Linux命令行KVM虚拟机的安装配置与基本使用
    Linux系统真正的优势以及学习方法
    一款在线编写接口文档的工具
    springboot前端传参date类型后台处理方式
    软件工程专业需要知道的缩写和专业名词
    七牛云图床及MPIC工具使用
    阿里云ECS云服务器CentOS部署个人网站
    【字】biang
    【车】打开车窗技巧
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/10473688.html
Copyright © 2020-2023  润新知