天天看点

60、数组类模板

1、预备知识

  • 模板参数可以是数值型参数(非类型参数)
template < typename T, int N >
void func()
{
	T a[N];						//使用模板参数定义局部数组
}
           
func<float, 10>();
           
  • 数值型模板参数的限制

    — 变量不能作为模板参数

    — 浮点数不能作为模板参数

    — 类对象不能作为模板参数

    — …

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

  • 有趣的面试题

    用你觉得最高效的方法求 1 + 2 + 3 +…+ N 的值

#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:
	static const int value = Sum<N - 1>::value + N;						//首先value是常量,其次存放在静态存储区
};

template <>
class Sum < 1 >
{
public:
	static const int value = 1;
};

int main()
{
	func<int, 10>();
	cout << endl;
	cout << "1+2+3+....10 = " << Sum<10>::value << endl;
	cout << "1+2+3+....100 = " << Sum<100>::value << endl;
	
	return 0;
}
           

这个程序主要是向我们介绍数组类模板以及用最高效的方法求 1 + 2 + 3 +…+ N 的值。最高效的原因在于模板参数是在编译阶段被处理的单元,在编译期间就已经确定了,我们后面的输出函数相当于就是输出一个变量的值。

2、数组模板类

Array.h

#ifndef _ARRAY_H_
#define _ARRAY_H_
#pragma once
template < typename T, int N >
class Array
{
	T m_array[N];
public:
	int length();
	bool set(int index, T value);
	bool get(int index, T& value);
	T& operator[](int index);
	T operator[](int index)const;
	virtual ~Array();
};
template < typename T, int N >
int Array< T, N >::length()
{
	return N;
}

template < typename T, int N >
bool Array< T, N >::set(int index, T value)
{
	bool ret = (index >= 0) && (index < N);
	if (ret)
	{
		m_array[index] = value;
	}
	return ret;
}

template < typename T, int N >
bool Array< T, N >::get(int index, T& value)
{
	bool ret = (index >= 0) && (index < N);
	if (ret)
	{
		value = m_array[index];
	}
	return ret;
}

template < typename T, int N >
T& Array< T, N >::operator[](int index)
{
	return m_array[index];
}

template < typename T, int N >
T Array< T, N >::operator[](int index)const
{
	return m_array[index];
}

template < typename T, int N >
Array< T, N >::~Array()
{
}

#endif
           

Array.cpp

#include <iostream>
#include <string>
#include "Array.h"

using namespace std;

int main()
{
	Array<char, 5> a;
	for (int i = 0; i < a.length(); i++)
	{
		a[i] = i + 'a';
	}
	for (int i = 0; i < a.length(); i++)
	{
		cout << a[i] << endl;
	}
	return 0;
}
           
60、数组类模板

程序二:

HeapArray.h

#ifndef HEAPARRAY_H
#define HEAPARRAY_H

template <typename T>
class HeapArray
{
private:
    T* m_pointer;
    int m_length;
    HeapArray(int length);
    HeapArray(const HeapArray<T>& obj);
    bool construct();
public:
    int length();
    static HeapArray<T>* NewInstance(int len);
    bool set(int index, T value);
    bool get(int index, T& value);
    T& operator[](int index);
    T operator[](int index)const;
    HeapArray<T>& operator=(const HeapArray<T>& obj);
    HeapArray<T>& self();
    virtual ~HeapArray();
};

template <typename T>
HeapArray<T>::HeapArray(int length)
{
    m_length = length;
}

template <typename T>
HeapArray<T>::HeapArray(const HeapArray<T>& obj)
{

}

template <typename T>
bool HeapArray<T>::construct()
{
    m_pointer = new T[m_length];
    return m_pointer != nullptr;
}

template <typename T>
int HeapArray<T>::length()
{
    return m_length;
}

template <typename T>
HeapArray<T>* HeapArray<T>::NewInstance(int len)
{
    HeapArray<T>* ret = new HeapArray<T>(len);
    if(!(ret && ret->construct()))
    {
        delete ret;
        ret = nullptr;
    }
    return ret;
}

template <typename T>
bool HeapArray<T>::set(int index, T value)
{
    bool ret = (index >= 0 && index < m_pointer);
    if(ret)
    {
        m_pointer[index] = value;
    }
    return ret;
}

template <typename T>
bool HeapArray<T>::get(int index, T& value)
{
    bool ret = (index >= 0 && index < m_pointer);
    if(ret)
    {
        value = m_pointer[index];
    }
    return ret;
}

template <typename T>
T& HeapArray<T>::operator[](int index)
{
    return m_pointer[index];
}

template <typename T>
T HeapArray<T>::operator[](int index)const
{
    return m_pointer[index];
}

template <typename T>
HeapArray<T>& HeapArray<T>::operator=(const HeapArray<T>& obj)
{
    if(this != &obj)
    {
        T* pointer = new T[obj.m_length];
        if(pointer)
        {
            for(int i = 0; i < obj.m_length; i++)
            {
                pointer[i] = obj.m_pointer[i];
            }
            delete []m_pointer;
            m_pointer = pointer;
            m_length = obj.m_length;
        }
    }
    return *this;
}

template <typename T>
HeapArray<T>& HeapArray<T>::self()
{
    return *this;
}

template <typename T>
HeapArray<T>::~HeapArray()
{
    delete []m_pointer;
}
#endif // HEAPARRAY_H

           

main.cpp

#include <iostream>
#include <string>
#include "HeapArray.h"
using namespace std;


int main()
{
	HeapArray<char>* a = HeapArray<char>::NewInstance(5);
	HeapArray<char>* b = HeapArray<char>::NewInstance(10);
	if (a && b)
	{
		HeapArray<char>& array = a->self();
		HeapArray<char>& brray = b->self();
		for (int i = 0; i < array.length(); i++)
		{
			array[i] = i+'a';
		}
		for (int i = 0; i < array.length(); i++)
		{
			cout << array[i] << endl;
		}
	}

	(*b) = (*a);
	cout << a->length() << endl;
	cout << b->length() << endl;

	delete a;
	delete b;
	return 0;
}
           
60、数组类模板

小结:

  • 模板参数可以是数值型参数
  • 数值型模板参数必须在编译期间唯一确定
  • 数组类模板是基于数值型模板参数实现的
  • 数组类模板是简易的线性表数据结构

重点提醒:

类模板在函数定义时,类的类型会变成 ClassName< T >:: 诸如这样的,对于构造函数,比如

HeapArray<T>::HeapArray(int length)

,只需要在前面加上ClassName< T >:: 即可。有些要加上两个,比如类型是类引用的,就要加两个。

HeapArray<T>& HeapArray<T>::operator=(const HeapArray<T>& obj)
           

在主函数里面,类的类型也变成了ClassName< T >。所以在定义对象的时候要变成

HeapArray<char>* a

继续阅读