第22课 - 类模板 - 下

第22课 - 类模板 - 下

    一.类模板的局部特化

        1.1 类模板可以定义多个类型参数

      
     Source Example 1.1:
                #include <iostream>


                /* run this program using the console pauser or add your own getch, system("pause") or input loop */
                using namespace std;

                template <typename T1, typename T2>
                class Test {
                public:
                    void print(T1 i, T2 j)
                    {
                        cout <<i + j <<endl;
                    }
                };

                int main(int argc, char** argv) {
                    
                    Test<double, int> t1;
                    
                    /* 输出10.8001 */
                    t1.print(10.001,8);
                    
                    return 0;
                }

        1.2 类模板可以被局部特化

            - 可以指定类模板的特定实现,并且要求某些类型参数依然必须得模板的用户指定。

      
      Source Example 1.2:
                #include <iostream>


                /* run this program using the console pauser or add your own getch, system("pause") or input loop */
                using namespace std;

                template <typename T1, typename T2>
                class Test {
                public:
                    void print(T1 i, T2 j)
                    {
                        cout <<i + j <<endl;
                    }
                };

                /* 类模板的局部特化,两个相同的参数相加 */
                template <typename T>
                class Test<T,T> {
                public:
                    void print(T i, T j)
                    {
                        cout << "print(T i, T j)" <<endl;
                        cout <<static_cast<T>(i + j) <<endl;
                    }
                };

                template <typename T>
                class Test<T,int> {
                public:
                    void print(T i, int j)
                    {
                        cout << "print(T i, int j)" <<endl;
                        cout <<i + j <<endl;
                    }
                };

                /* 指针的局部特化 */
                template  <typename T1, typename T2>
                class Test<T1*,T2*> {
                public:
                    void print(T1* i, T2* j)
                    {
                        cout << "print(T1* i, T2* j)" <<endl;
                    }
                };

                int main(int argc, char** argv) {
                    
                    /* t1会优先匹配到第三个模板<T,int> */
                    Test<double, int> t1;
                    /* t2匹配到第二个和第三个模板,地位相等,都是局部特化,因此会报错 */
                    //Test<int, int> t2;
                    /* 匹配到第二个模板 */
                    Test<long, long> t2;
                    /* t1会优先匹配到第三个模板<T,int> */
                    Test<float, int> t3;
                    /* t4会匹配到第一模板和第4个模板,会报错 */
                    //Test<int*, int*> t4;
                    /* 匹配到第4个模板<T1*, T2*> */
                    Test<long*, int*> t4;
                    
                    long i = 0;0
                    int j = 0;
                    
                    
                    t1.print(10.001,8);
                    /* 会优先选择特化的类模板 */
                    t2.print(2, 3);
                    t3.print(3,4);
                    t4.print(&i, &j);
                    
                    return 0;
                }

            输出结果如下:


            

        1.3 为什么需要特化,而不重新定义新类?

            1.1.3 特化和重新定义新类看上去本质没有区别,但是如果定义新类,那么将变成一个类模板一个新类,
                    使用的时候需要考虑就是使用类模板还是用新类
            1.1.4 而特化可以统一方式使用类模板和特化类,编译器自动优先选择特化类
            

        1.4 非类型模板参数

            -函数模板和类模板的参数可以是普通数值

          
 Source Example1.4:
            #include <iostream>


            /* run this program using the console pauser or add your own getch, system("pause") or input loop */
            using namespace std;

            template <typename T, int N>
            void func()
            {
                T array[N] = {0};
                
                for (int i = 0; i < N; i++)
                {
                    array[i] = i + 1;
                    cout<<array[i]<<" " ;
                }
                cout<<endl;
            }

            int main(int argc, char** argv) {
                
                func<int, 5>();
                func<float, 10>();
                
                return 0;
            }

            1.5 非类型模板参数与特化

              
 Source Example1.5(计算1加到某个自然数):
                    #include <iostream>

                    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
                    using namespace std;

                    template <int N>
                    class Sum{
                    public:
                        /* 变为真正意义的常量,放入符号表 */
                        static const int VALUE = Sum<N-1>::VALUE + N;
                    };

                    template <>
                    class Sum<1>{
                    public:
                        /* 变为真正意义的常量,放入符号表 */
                        static const int VALUE = 1;
                    };
                    int main(int argc, char** argv) {
                        
                        /* 编译时计算出来了 */
                        cout<<Sum<100>::VALUE<<endl;
                        
                        return 0;
                    }
            

            1.6 非类型模板参数的限制

                1.6.1  变量不能作为模板参数
                  
                  /* 会报错 */
                    int n = 100;
                    cout<<Sum<n>::VALUE<<endl; 
                1.6.2 浮点数和类对象不能作为模板参数
                1.6.3 全局指针不能作为模板参数
            

           注意:编译器的推导是在编译阶段完成的。因此,编译器的推导必须依赖于特化类,否则推导过程无法结束。(递归思想)


    二.工程问题

        2.1 在实际工程中内存操作时bug的重要来源

        2.2 C++将对内存交给程序员自由使用,因此

            2.2.1 未及时释放,将产生内存泄漏
            2.2.2 重复释放同一段内存,行为未知
            2.2.3 使用越界,操作了不属于自己的内存
         

        思考->怎样最大避开上述的使用问题?

            

            a. 内存越界的问题常发生在数组的使用中.

                解决方案:数组类

               工程中,在非特殊情况下,要求开发者使用预先编写的数组类对象代替C语言中的原生数组

                

            b. 内存泄漏和内存多次释放常发生于指针的使用过程中

                解决方案:智能指针

                工程中,要求开发者使用预先编写的智能指针对象代替C语言中的原生指针

            

                工程中的智能指针是一个类模板

                    1. 通过构造函数接管申请的堆内存

                    2. 通过西沟函数确保堆内存被及时释放

                    3. 通过重载指针运算符*和->模拟指针的行为

                    4. 通过重载比较运算符==和!=模拟指针的比较

                

       

           
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值