用类模板实现容器存储自定义数据类型(类似于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次。

原文地址:https://www.cnblogs.com/jswu-ustc/p/8527597.html

时间: 2024-10-16 00:57:03

用类模板实现容器存储自定义数据类型(类似于STL里面的vector)的相关文章

用类模板实现容器(STL里面的vector)

STL里面的很多容器,都是用类模板技术实现的.以vector为例,说明如何使用类模板技术来实现. 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<<

NSUserdefaults 简介以及存储自定义数据类型的方法

一.了解NSUserDefaults以及它可以直接存储的类型 NSUserDefaults是一个单例,在整个程序中只有一个实例对象,他可以用于数据的永久保存,而且简单实用,这是它可以让数据自由传递的一个前提,也是大家喜欢用它保存简单数据的一个主要原因. 使用 NSUserDefaults 存储自定义对象的最初,我们必须认识NSUserDefaults可以存储哪一些类型的数据,下面一一列出: NSUserDefaults支持的数据类型有:NSNumber(NSInteger.float.doubl

STL容器set()---&gt;自定义数据类型

set容器中不能插入重复的元素,需要其插入的元素有比较大小(<).相等(==) 的逻辑判断,这是因为set中的元素是有序排列, 默认从小到大排列 std::set<type,std::less<type>> mySet ; 等同于 std::set<type> mySet; 所以需要元素的数据类型 具有 大小.相等判断的函数. 对于编译器标准定义数据类型(如 int,float,double等),系统已经定义大小判断:但对于自定义数据就要注意自己动手添加这些函数.

自定义Button,复写里面的onKeyDown,不起作用

李刚的Android疯狂讲义真是"疯狂",浪费了3天时间,到底是他的代码有问题,还是怎么的不得而知. 问题描述:他的书里面第3.3基于回调事件处理Propagation的例程.是为了掩饰基于回调事件传播的例程序,源代码如下: MyButton.java public class MyButton extends Button { public MyButton(Context context , AttributeSet set) { super(context , set); } @

【剑仙教程】易语言的结构体。自定义数据类型。

1楼. [剑仙教程]易语言的结构体.自定义数据类型. 在易语言中,有基本数据类型,自定义数据类型. 自定义数据类型,在C语言/C++中称为结构体.这是面向对象和类的编程. . . 先上代码.打开易语言的IDE,IDE,是开发环境. 点击“插入”菜单,选择“数据类型” 这时,代码编辑框就会增加一个数据类型的窗口. 把“数据类型1”命名为“精易_座标”,勾选“公开项”. 这样,一个 精易_座标 的类就做好了. . 再按回车键,给这个类增加2个成员. x 整数型 y 整数型 . 访问时,直接写代码就O

C++类模板声明与定义为何不能分开

C++中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的大小的.只有模板被真正使用的时候,编译器才知道,模板套用的是什么类型,应该分配多少空间.这也就是模板类为什么只是称之为模板,而不是泛型的缘故. 既然是在编译的时候,根据套用的不同类型进行编译,那么,套用不同类型的模板类实际上就是两个不同的类型,也就是说,stack<int>和stack<char>是两个不同的数据类型,他们共同的成员函

数组类模板(四十九)

之前我们学习了类模板,今天我们来看看数组类模板.模板参数可以是数值型参数(非类型参数),如下 使用数值型模板参数是有限制的,如:a> 变量不能作为模板参数:b> 浮点数不能作为模板参数:c> 类对象不能作为模板参数.其本质是模板参数是在编译阶段被处理的单元,因此在编译阶段必须准确无误的唯一确定. 下来我们用函数模板来实现一个面试题:用最高效的方法求 1+2+3+...+N 的值. #include <iostream> #include <string> usin

类模板深度剖析

多参数类模板类模板可以定义任意多个不同的类型参数template <typename T1, typename T2>class Test{public: void add(T1 a, T2 b);}; 使用上述的类模板: Test<int ,float> t; 类模板可以被特化:即特殊化-指定类模板的特定实现-部分类型参数必须显示指定-根据类型参数分开实现类模板template<typename T1, typename T2>class Test{ }; 上面的类模

类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

 1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPushButton> #include <QLabel> template<class T> class run { public: T w; void show() { w.show(); } void settext() { w.setText("A"); }