示例导入:
//vectorTemplateClass.h -- create my vector class template #pragma once #include#include template class Vector { protected: T *array; int m_len; public: //Default Constructor Vector(); //Copy constructor Vector(const Vector & temp); //Destructor ~Vector(); //overload operator methods Vector operator+(const Vector & v)const; Vector& operator+=(const Vector & v); Vector operator-(const Vector & v)const; Vector& operator-=(const Vector & v); Vector operator-()const; T operator*(const Vector & v)const; Vector operator*(T per)const; Vector& operator=(const Vector & v); T& operator[](int i); T operator[](int i)const; //friend methods template friend bool operator==(const Vector & v1, const Vector & v2); template friend bool operator!=(const Vector & v1, const Vector & v2); template friend std::ostream& operator<<(std::ostream& os, const Vector & v); template friend std::istream& operator>>(std::istream& is, Vector & v); //template friend Vector& operator*(T per, const Vector & v); //common class methods void reverse(); void swap(Vector & v); int size() { return m_len; } int find(T n); Vector& resize(int size, T n); void clear(); T pop(); double distance(); }; //Default Constructor template Vector ::Vector() { m_len = 0; array = new T[1]; array = NULL; } //Copy Constructor template Vector ::Vector(const Vector & temp) { m_len = temp.m_len; array = new T[m_len]; for (int i = 0; i < temp.m_len; i++) array[i] = temp.array[i]; } //Destructor template Vector ::~Vector() { delete[] array; } //overload operator+ template Vector Vector ::operator+(const Vector & v)const { if (m_len != v.m_len) { std::cerr << "Dimensions are inconsistent: " << std::endl; std::cerr << "One dimensions is " << m_len << ", the other is " << v.m_len << std::endl; std::exit(EXIT_FAILURE); } Vector v2; v2.m_len = m_len; v2.array = new T[m_len]; for (int i = 0; i < m_len; i++) v2.array[i] = array[i] + v.array[i]; return v2; } //overload operator += template Vector & Vector ::operator+=(const Vector & v) { if (m_len != v.m_len) { std::cerr << "Dimensions are inconsistent: " << std::endl; std::cerr << "One dimensions is " << m_len << ", the other is " << v.m_len << std::endl; std::exit(EXIT_FAILURE); } for (int i = 0; i < m_len; i++) array[i] += v.array[i]; return *this; } //overload operator - template Vector Vector ::operator-(const Vector & v)const { if (m_len != v.m_len) { std::cerr << "Dimensions are inconsistent: " << std::endl; std::cerr << "One dimensions is " << m_len << ", the other is " << v.m_len << std::endl; std::exit(EXIT_FAILURE); } Vector v2; v2.m_len = m_len; v2.array = new T[m_len]; for (int i = 0; i < m_len; i++) v2.array[i] = array[i] - v.array[i]; return v2; } //overload operator -= template Vector & Vector ::operator-=(const Vector & v) { if (m_len != v.m_len) { std::cerr << "Dimensions are inconsistent: " << std::endl; std::cerr << "One dimensions is " << m_len << ", the other is " << v.m_len << std::endl; std::exit(EXIT_FAILURE); } for (int i = 0; i < m_len; i++) array[i] -= v.array[i]; return *this; } //overload operator-(Contary vector) template Vector Vector ::operator-()const { Vector v; v.m_len = m_len; v.array = new T[m_len]; for (int i = 0; i < m_len; i++) v.array[i] = -array[i]; return v; } //overload operator*(dot metrix) template T Vector ::operator*(const Vector & v)const { if (m_len != v.m_len) { std::cerr << "Dimensions are inconsistent: " << std::endl; std::cerr << "One dimensions is " << m_len << ", the other is " << v.m_len << std::endl; std::exit(EXIT_FAILURE); } T sum = 0; for (int i = 0; i < m_len; i++) sum += array[i] * v.array[i]; return sum; } //overload operator* template Vector Vector ::operator*(T per)const { Vector v; v.m_len = m_len; v.array = new T[m_len]; for (int i = 0; i < m_len; i++) v.array[i] = array[i] * per; return v; } //overload operator= template Vector & Vector ::operator=(const Vector & v) { if (*this == v) return *this; delete[] array; m_len = v.m_len; array = new T[m_len]; for (int i = 0; i < v.m_len; i++) array[i] = v.array[i]; } //revisable template T& Vector ::operator[](int i) { if (i >= m_len || i <= -m_len) { std::cerr << "Error in array limits: " << i << "is out of range!" << std::endl; std::exit(EXIT_FAILURE); } if (i < 0) return array[m_len + i]; return array[i]; } //unchangeable template T Vector ::operator[](int i)const { if (i >= m_len || i <= -m_len) { std::cerr << "Error in array limits: " << i << "is out of range!" << std::endl; std::exit(EXIT_FAILURE); } if (i < 0) return array[m_len + i]; return array[i]; } //friend methods template bool operator==(const Vector & v1, const Vector & v2) { bool flag = true; if (v1.m_len != v2.m_len) return !flag; for (int i = 0; i < v1.m_len; i++) { if (v1.array[i] != v2.array[i]) return !flag; } return flag; } template bool operator!=(const Vector & v1, const Vector & v2) { bool flag = true; if (v1.m_len != v2.m_len) return flag; for (int i = 0; i < v1.m_len; i++) { if (v1.array[i] != v2.array[i]) return flag; } return !flag; } template std::ostream& operator<<(std::ostream& os, const Vector & v) { if (v.m_len <= 0) return os; os << "("; if (v.m_len > 1) { for (int i = 0; i < v.m_len - 1; i++) os << v.array[i] << ", "; os << v.array[v.m_len - 1] << ")"; } else os << v.array[v.m_len - 1] << ")"; return os; } template std::istream& operator>>(std::istream& is, Vector & v) { std::cout << "Please enter dimension: "; is >> v.m_len; v.array = new T[v.m_len]; std::cout << "Please input the vector: "; for (int i = 0; i < v.m_len; i++) is >> v.array[i]; return is; } //template //Vector & operator*(T per, const Vector & v) //{ // return v * per; //} template void Vector ::reverse() { if (m_len != 0) { for (int i = 0;; i++) { T temp = array[i]; array[i] = array[m_len - i - 1]; array[m_len - i - 1] = temp; if (i >= m_len - i - 1) break; } } } template void Vector ::swap(Vector & v) { Vector temp; temp = v; v = *this; *this = temp; } template int Vector ::find(T n) { if (m_len != 0) for (int i = 0; i < m_len; i++) if (array[i] == n) return i + 1; std::cout << "Can't find " << n << " in vector!" << std::endl; return 0; } template Vector & Vector ::resize(int size, T n) { delete[]array; m_len = size; array = new T[m_len]; for (int i = 0; i < m_len; i++) array[i] = n; return *this; } template void Vector ::clear() { delete[]array; array = NULL; m_len = 0; } template T Vector ::pop() { T temp = array[m_len - 1]; delete array[m_len - 1]; m_len--; return temp; } template double Vector ::distance() { T sum = 0; for (int i = 0; i < m_len; i++) sum += array[i]; return sqrt(sum); }
注释:
1.类开头、友元函数前以及类外定义方法时需要声明泛型名称Type
template
而在类声明中定义了方法(内敛定义),则可以省略模板前缀和类限定符。
2.不可以将模板成员函数放在独立的实现文件中,因为模板不是函数,不能单独编译,同时在使用
前不占用内存,只有在被实例化或具体化后才会有自己的内存空间。
3.模板类友元函数声明和定义前都需要声明泛型名称,如:
templatefriend std::ostream& operator<<(std::ostream& os, const Vector & v);
4.模板类函数在定义时,返回类型、域名、参数数据类型都需要泛型名称,而在类中声明时为
Stack,这是Stack
Stack & operator=(const Stack & st) …… templateStack & Stack ::operator=(const Stack & st)
5.如果要在类声明中声明数组,在具体化时就确定数组元素个数,则可以有以下声明:
templateclass ArrayTP { private: T arr[n]; ……
使用类模板时数据类型可以用ArrayTP
6.模板类也可以用作基类,在继承时的用法类似,仅仅需要在继承声明时加上模板类的数据类型声
明,同时也可有虚函数如:
virtual T & operator[](int i);
7.模板类也可以用作其他模板的类型参数,即可以递归使用:
ArrayTP< ArrayTP, 10> twodes;
与之等价的常规数组的声明为int twodes[10][5];
若无数组维数,则两个>之间至少需要一个空白字符将其分开,防止与>>混淆:
Array< Stack> asi;
8.在类模板实例化时,调用构造函数以及声明域名都需要的时类似于Stack
是Stack
9.隐式实例化:声明一个或多个对象,指出所需类型,而编译器使用通用模板提供的处方生成具体
的类定义
ArrayTp* pt; #1 pt = new ArrayTp #2
第一条语句只是指针,并不需要对象,因此不会生成类定义,而第二条语句导致编译器生成类定义
并且根据该定义创建一个对象。
显示实例化:需要用到关键字template
template class ArrayTP;
虽然没有创建或提及类对象,编译器也将会生成类定义
10.部分具体化
templateclass Pair
11.嵌套模板
templateclass beta { private: template class hold; hold q; hold n; …… …… template template U beta ::blab(U u, T t> { return (n.Value() + q.Value * u /t; }
12.模板类的约束模板友元函数即将友元函数声明为模板:
//类定义前声明每个模板函数 …… templatevoid counts(); template void report(T &); …… //在类方法中再次将模板声明为友元 template class class_name { …… friend void counts(); friend void report<>(class_name &); …… //友元函数定义 ……
13.模板别名:
关键字typedef类型:typedef std::array
关键字using类型:using arrtype = std::array



