用类模板实现容器存储自定义数据类型(类似于STL里面的vector)
上一节里面已经提到了,用类模板存储自定义的数据类型,如Teacher类型时,需要重载Teacher类的拷贝构造函数,“=”操作符,"<<"操作符,特别要注意深拷贝和浅拷贝的问题。
例如:
1 //1.myvector.h文件 2 #ifndef MYVECTOR_H 3 #define MYVECTOR_H 4 5 #include <iostream> 6 using namespace std; 7 8 template<typename T> 9 class Myvector 10 { 11 friend ostream& operator<<<T>(ostream& out,Myvector<T>& obj); 12 public: 13 Myvector(int size);//构造函数 14 Myvector(Myvector<T>&);//拷贝构造函数 15 ~Myvector();//析构函数 16 17 public: 18 Myvector<T>& operator=(const Myvector<T>& obj); 19 T& operator[](int index); 20 int getlen(){return my_len;} 21 22 private: 23 T* my_space;//模板数组的首地址 24 int my_len;//模板数组的长度,等于最大索引数+1 25 }; 26 27 #endif 28 29 30 //2.myvector.cpp文件 31 #include <iostream> 32 #include "myvector.h" 33 34 35 using namespace std; 36 37 //构造函数 38 template<typename T> 39 Myvector<T>::Myvector(int size) 40 { 41 my_len=size; 42 my_space=new T[my_len]; 43 if(my_space==NULL) 44 { 45 cout<<"调用构造函数 分配内存失败!"<<endl; 46 return; 47 } 48 } 49 50 //拷贝构造函数,深拷贝。拷贝构造函数也是构造函数,一开始my_len,my_space的值都是没有的(随机数),不存在释放什么的,全是要靠自己复制才会有 51 template <typename T> 52 Myvector<T>::Myvector(Myvector<T>& obj) 53 { 54 my_len=obj.my_len; 55 my_space=new T[my_len]; 56 57 for(int i=0;i<my_len;i++) 58 { 59 my_space[i]=obj.my_space[i]; 60 } 61 } 62 63 //析构函数 64 template<typename T> 65 Myvector<T>::~Myvector() 66 { 67 cout<<"调用模板类的析构函数"<<endl; 68 if(my_space!=NULL) 69 { 70 delete [] my_space; 71 my_space=NULL; 72 my_len=0; 73 } 74 } 75 76 //重载"[]"操作符 77 template<typename T> 78 T& Myvector<T>::operator[](int index) 79 { 80 return this->my_space[index]; 81 } 82 83 84 //重载"="操作符 85 template<typename T> 86 Myvector<T>& Myvector<T>::operator=(const Myvector<T>& obj) 87 { 88 if(my_space!=NULL) 89 { 90 my_len=0; 91 delete [] my_space; 92 my_space = NULL; 93 } 94 95 my_len=obj.my_len; 96 for(int i=0;i<my_len;i++) 97 { 98 my_space[i]=obj.my_space[i]; 99 } 100 101 return *this; 102 } 103 104 105 //重载"<<"运算符 106 template<typename T> 107 ostream& operator<<(ostream& out,Myvector<T>& obj) 108 { 109 for(int i=0;i<obj.my_len;i++) 110 { 111 out<<obj.my_space[i]<<" "; 112 } 113 return out; 114 } 115 116 117 //3.main.cpp文件 118 #include <iostream> 119 #include"myvector.cpp" 120 #include"myteacher.h" 121 #include<string> 122 123 using namespace std; 124 125 class Teacher 126 { 127 friend ostream& operator<<(ostream& out,const Teacher& t); 128 public: 129 //构造函数,不带参 130 Teacher() 131 { 132 age=0; 133 name=NULL; 134 } 135 136 //构造函数,带参 137 Teacher(int a,char* n) 138 { 139 age=a; 140 int name_len=strlen(n); 141 name=new char[name_len+1]; 142 strcpy(name,n); 143 } 144 145 //拷贝构造函数 146 Teacher(const Teacher& t) 147 { 148 age=t.age; 149 int name_len=strlen(t.name); 150 name=new char[name_len+1]; 151 strcpy(name,t.name); 152 } 153 154 //析构函数 155 ~Teacher() 156 { 157 cout<<"调用Teacher类的析构函数"<<endl; 158 if(name!=NULL) 159 { 160 age=0; 161 delete [] name; 162 name=NULL; 163 } 164 } 165 166 //重载"="操作符 167 Teacher& operator=(Teacher& t) 168 { 169 if(name!=NULL) 170 { 171 delete [] name; 172 name=NULL; 173 age=0; 174 } 175 176 int name_len=strlen(t.name); 177 name=new char[name_len+1]; 178 strcpy(name,t.name); 179 age=t.age; 180 181 return *this; 182 } 183 184 void printT() 185 { 186 cout<<age<<" "<<name<<endl; 187 } 188 189 190 private: 191 int age; 192 char* name; 193 }; 194 195 ostream& operator<<(ostream& out,const Teacher& t) 196 { 197 out<<t.age<<" "<<t.name; 198 return out; 199 } 200 201 202 int main() 203 { 204 Teacher t1(26,"Wu"),t2(33,"Li"); 205 206 Myvector<Teacher> v(3); 207 208 v[0]=t1; 209 v[1]=t2; 210 211 cout<<v[0]<<endl; 212 cout<<v[1]<<endl; 213 214 215 216 return 0; 217 }
上述代码的执行结果是:
26 Wu
33 Li
调用模板类的析构函数
调用Teacher类的析构函数
调用Teacher类的析构函数
调用Teacher类的析构函数
调用Teacher类的析构函数
调用Teacher类的析构函数
之所以会5次调用Teacher类的析构函数,是因为定义了1个myvector v(3),即v是包含3个元素的数组,定义了2个Teacher类的对象t1和t2。
然后把v[0]=t1,v[1]=t2,则v[2]是空的。执行析构函数的时候,要析构v里面的元素3次,即3次调用Teacher类的析构函数;调用Teacher类对象的析构函数2次,即t1和t2各析构一次,总共析构了2+3=5次。