• 第六十课、数组类模板


    一、数值型参数(类型参数)

    1、模板参数可以是数值型参数

    2、数值型模板参数的限制

    (1)、变量不能作为模板参数

    (2)、浮点数不能作为模板参数

    (3)、类对象不能作为模板参数

    (4)、等等

    3、数值型参数的本质

    (1)、模板参数是在编译阶段被处理的单元,因此,在编译阶段必须准确无误唯一确定

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    template < typename T, int N>
    void func()
    {
        T a[N] = {0};
        
        for (int i=0; i<N; i++)
        {
            a[i] = i;
        }
        
        for (int i=0; i<N; i++)
        {
            cout << a[i] << endl;
        }
    }
    
    template <int N>
    class Sum
    {
    public:
        //注意以下语句采用递归定义,即当调用Sum<N>::VALUE时,
        //编译器认为其值等于Sum<N-1>::VALUE + N;于是就出现了
        //递归,直至Sum<1>时会找到后面特化的类模定义,因那里
        //Sum<1>::VALUE=1,于是递归结束。
        //注意,在这程中,会依次产生Sum<100>、Sum<99>、...、Sum<1>
        //等100个类,而每个类里面都有一个静态成员变量VALUE值,因其
        //位于不同的类中,本质上在静态数据中会开辟100多个int型空间
        //来存储这些变量。在编译器会进行优化,把中间这些不用的类给
        //丢弃,最保存最终的结果,即内存中只有一个静态VALUE变量的值。
        static const int VALUE = Sum<N-1>::VALUE + N;
    };
    
    template<>
    class Sum<1>
    {
    public:
        //以下语句在声明和定义起并对VALUE进行了初始化。这是合法的
        //1. 如果只有单独的static int VALUE为什么不能直接初始化?
        //   因为C++里声明和定义是分开的,当编译器看到那样的语句时
        //   会认为这是声明,并没有定义,也就是空间还没分配好,需要在
      //类的外部先另外分配空间才能初始化

    //2. 如果只有const int VALUE为什么也不能直接初始化? // 这也是同样的道理,这里的VALUE属于对象,而对象要用使用时 // 才分配空间,而在这里是无法分配空间的。可以在构造函数的初始化列表中初始化
      // const在类不同对象中可能值不一样,也就是说const在单个对象中是不可变的,但对于类是可变的
    //3. static const int VALUE = 1;为什么这样的语句合法? // 当这两种的结合,其意义就跟一般的全局常量差不多,
      //进入符号表并且初始化为1
    static const int VALUE = 1; }; int main() { cout << "1 + 2 + 3 + ...+ 10 = " << Sum<10>::VALUE << endl;//VALUE的值在编译期就确定了,所有非常高效 cout << "1 + 2 + 3 + ...+ 100 = " << Sum<100>::VALUE << endl; return 0; }

    用数组类模板来实现数组类:

    //Array.h

    #ifndef  _ARRAY_H_
    #define  _ARRAY_H_
    template
    <typename T, int N>
    class Array
    {
    protected:
        T a[N];
    public:
        int length();
        int length()const;//const对象时用,与上面的函数构造重载
        bool get(int index, T& value);
        bool set(int index, T value);
        T& operator [] (int index);  //返回引用可以做左值
        virtual ~Array();//允许被继承,声明为虚函数
    };
    
    #endif
    
    template
    <typename T, int N>
    int Array<T, N>::length()
    {
        return N;
    }
    
    template
    <typename T, int N>
    int Array<T, N>::length()const
    {
        return N;
    }
    
    
    template
    <typename T, int N>
    bool Array<T, N>::set(int index, T value)
    {
        bool ret = (0 < index) && (index < length());
        
        if(ret)
        {
            a[index] = value;
        }
        
        return ret;
    }
    
    template
    <typename T, int N>
    bool Array<T, N>::get(int index, T& value)
    {
    bool ret = (0 < index) && (index < length());
        
        if(ret)
        {
            value = a[index];
        }
        
        return ret;
    }
    
    template
    <typename T, int N>
    T& Array<T, N>::operator [] (int index)
    {
        return a[index];
    }
    
    template
    <typename T, int N>
    Array<T, N>::~Array()
    {
    };

    //HeapArray.h

    #ifndef _HEAPArray_H_
    #define _HEAPArray_H_
    
    template
    < typename T >
    class HeapArray
    {
    private:
        T* m_poiter; 
        int m_length;
        
        HeapArray(int length);//构造函数私有,不允许继承
        HeapArray(const HeapArray<T>& obj);
        bool construct();
    public:
        static HeapArray<T>* NewInstance(int length);
        int length();
        int length()const;//const对象时用
        bool get(int index, T& value);
        bool set(int index, T value);
        T& operator [] (int index);
        HeapArray<T>& self();   
        ~HeapArray();
    };
    
    template
    < typename T >
    HeapArray< T >::HeapArray(int length)
    {
        m_length = length;
    }
    
    template
    < typename T >
    bool HeapArray< T >::construct()
    {
        
        m_poiter = new T[m_length];
    
        return m_poiter != NULL;
    }
    
    template
    < typename T >
    HeapArray< T >* HeapArray< T >::NewInstance(int length)
    {
        HeapArray< T >* ret = new HeapArray(length);
        
        if(!(ret && (ret->construct())))
        {
            delete ret;
            ret = NULL;
        }
        
        return ret;
    }
    
    template
    < typename T >
    int HeapArray< T >::length()
    {
        return m_length;
    }
    
    template
    < typename T >
    int HeapArray< T >::length()const
    {
        return m_length;
    }
    
    template
    < typename T >
    bool HeapArray< T >::get(int index, T& value)
    {
        bool ret = (0 < index) && (index < length());
        if(ret)
        {
            value = m_poiter[index];
        }
        
        return ret;
    }
    
    template
    < typename T >
    bool HeapArray< T >::set(int index, T value)
    {
        bool ret = (0 < index) && (index < length());
        if(ret)
        {
            m_poiter[index] = value;
        }
        
        return ret;
    }
    
    template
    < typename T >
    T& HeapArray< T >::operator [] (int index)
    {
        return m_poiter[index];
    }
    
    template
    < typename T >
    HeapArray<T>& HeapArray< T >::self()
    {
        return *this;
    }  
    
    
    template
    < typename T >
    HeapArray< T >::~HeapArray()
    {
        delete[] m_poiter;
    }
    
    #endif

    //main.cpp

    #include<iostream>
    #include"Array.h"
    #include"HeapArray.h"
    
    using namespace std;
    
    int main()
    {
    /********************************Array*********************************/
        Array< double, 5 > a1;
        
        int length = a1.length();    
        cout << "a1.length() = " << a1.length() << endl;
        
        for(int i=0; i<a1.length(); i++)
        {
            a1[i] = i + 1;
        }
        
        for(int i=0; i<a1.length(); i++)
        {
            cout << a1[i] << endl;
        }
        
        const Array< int, 10 > a2;
        cout << "a1.length() = " << a2.length() << endl;
        cout << endl;
    /*****************************HeapArray*********************************/  
      
        HeapArray<int>* a3 =  HeapArray< int > :: NewInstance(15);  
        if(a3 != NULL)
        {
            HeapArray<int>& array = a3->self();
            cout << "array.length() = " << array.length() << endl;
            
            for(int i=0; i<array.length(); i++)
            {
                array[i] = i + 1;
            }
            
            for(int i=0; i<array.length(); i++)
            {
                cout << array[i] << endl;
            } 
        }
        
        delete a3;//记得要销毁对象
    
        
        return 0;
    }

    二、小结

    (1)、模板参数可以是数值型参数

    (2)、数值型参数必须在编译期唯一确定

    (3)、数组类模板是基于数值型模板参数实现的

    (4)、数组类模板是简易的线性表数据结构

  • 相关阅读:
    Python深拷贝和浅拷贝解析
    python中count函数的用法
    Jenkins + gitlab + maven 自动打包部署项目
    nio和bio得区别
    nginx负载均衡的5种策略
    接口测试常见bug
    接口自动化面试4
    pass 语句
    if 语句
    while循环
  • 原文地址:https://www.cnblogs.com/gui-lin/p/6377593.html
Copyright © 2020-2023  润新知