【泛型编程】类模板实现简单的vector容器

简介: 【泛型编程】类模板实现简单的vector容器

首先创建一个类的.h和.cpp文件,分别如下

UserVector.h文件

1. #pragma once //只包含一次
2. 
3. #include <iostream>
4. using namespace std;
5. 
6. template<typename user_t>
7. class UserVector
8. {
9. public:
10.   //构造函数与析构函数
11.   UserVector(int len = 0); //有了默认初始参数,不需要在写无参构造函数 UserVector();
12.   UserVector(UserVector<user_t>& v); //UserVector<user_t> 必须指明类型来告诉编译器如何分配内存
13.   ~UserVector();
14. public:
15.   //重载函数
16.   user_t& operator[](int index);
17.   friend ostream& operator<< <user_t> (ostream& out, UserVector<user_t>& u);
18.   UserVector<user_t>& operator=(UserVector<user_t>& u);
19. private:
20.   int   len;
21.   user_t* p;
22. };

其中

#pragma once

表示只包含一次该头文件,防止重复包含导致的重定义,相当于C语言中的

1. #ifndef _USER_VECTOR_H
2. #define _USER_VECTOR_H
3. 
4. /*
5. 程序代码
6. */
7. 
8. #endif

UserVector.cpp文件

1. #include "UserVector.h"
2. 
3. template<typename user_t>
4. UserVector<user_t>::UserVector(int len)
5. {
6.  this->len = len;
7.  this->p = new user_t[this->len];
8. }
9. 
10. template<typename user_t>
11. UserVector<user_t>::UserVector(UserVector<user_t>& v)
12. {
13.   this->len = v.len;
14.   this->p = new user_t[this->len];
15.   for (int i = 0; i < this->len; i++)
16.   {
17.     this->p[i] = v.p[i];
18.   }
19. }
20. 
21. template<typename user_t>
22. UserVector<user_t>::~UserVector()
23. {
24.   if (this->p != NULL)
25.   {
26.     delete[] this->p;
27.   }
28.   this->p = NULL;
29.   this->len = 0;
30. }
31. 
32. template<typename user_t>
33. user_t& UserVector<user_t>::operator[](int index)
34. {
35.   return this->p[index];
36. }
37. 
38. template<typename user_t>
39. //std::ostream& operator<< <user_t> (std::ostream& out, UserVector<user_t>& u)
40. //错误  C2768 “operator << ”: 非法使用显式模板参数  
41. std::ostream& operator<<(std::ostream& out, UserVector<user_t>& u)
42. {
43.   for (int i = 0; i < u.len; i++)
44.   {
45.     out << u.p[i] << " ";
46.   }
47.   return out;
48. }
49. 
50. template<typename user_t>
51. UserVector<user_t>& UserVector<user_t>::operator=(UserVector<user_t>& u)
52. {
53.   if (this->p != NULL)
54.   {
55.     delete[] this->p;
56.     //无需置NULL,因为下面立马要修改
57.   }
58. 
59.   this->len = u.len;
60.   this->p = new user_t[this->len];
61. 
62.   for (int i = 0; i < this->len; i++)
63.   {
64.     this->p[i] = u.p[i];
65.   }
66. 
67.   return *this;
68. }

这里注意,在类模板中重载运算符的时候一定不能乱用友元函数,一般只有重载左移右移运算符时,才能使用友元函数,否则会报各种错误,并且在重载左移右移运算符的时候,函数声明一定要这样声明

friend ostream& operator<< <user_t> (ostream& out, UserVector<user_t>& u);

主测试函数函数如下

1. #define _CRT_SECURE_NO_WARNINGS
2. 
3. #include <iostream>
4. using namespace std;
5. 
6. //#include "UserVector.h" //报一堆错
7. #include "UserVector.cpp"
8. 
9. void FuncTest1()
10. {
11.   //1. int 类型的容器
12.   UserVector<int> i1(10);
13.   for (int i = 0; i < 10; i++)
14.   {
15.     i1[i] = i;
16.   }
17.   cout << "i1: " << i1 << endl;
18. 
19.   UserVector<int> i2 = i1;
20.   cout << "i2: " << i2 << endl;
21. 
22.   UserVector<int> i3;
23.   i3 = i2;
24.   cout << "i3: " << i3 << endl;
25. 
26.   //2. char
27.   UserVector<char> c1(3);
28.   c1[0] = 'a';
29.   c1[1] = 'b';
30.   c1[2] = 'c';
31.   cout << "c1: " << c1 << endl;
32. 
33.   UserVector<char> c2;
34.   c2 = c1;
35.   cout << "c2: " << c2 << endl;
36. }
37. 
38. class People
39. {
40. public:
41.   People()
42.   {
43.     this->age = 0;
44.     this->name = NULL;
45.   }
46.   People(int age, const char* p) //装入容器时,必须要有拷贝构造函数
47.   {
48.     this->age = age;
49.     this->name = new char[strlen(p) + 1];
50.     strcpy(this->name, p);
51.   }
52.   People(People& p)
53.   {
54.     this->age = p.age;
55.     this->name = new char[strlen(p.name) + 1];
56.     strcpy(this->name, p.name);
57.   }
58.   ~People()
59.   {
60.     if (this->name != NULL)
61.     {
62.       delete[] this->name;
63.     }
64.     this->name = NULL;
65.     this->age = 0;
66.   }
67. public:
68.   People& operator=(People& p)
69.   {
70.     if (this->name != NULL)
71.     {
72.       delete[] this->name;
73.     }
74. 
75.     this->name = new char[strlen(p.name) + 1];
76.     this->age = p.age;
77.     strcpy(this->name, p.name);
78. 
79.     return *this;
80.   }
81.   friend ostream& operator<<(ostream& out, People& p)
82.   {
83.     out << p.name << ": " << p.age << endl;
84.     return out;
85.   }
86. private:
87.   int   age;
88.   char* name;
89. };
90. 
91. void FuncTest2()
92. {
93.   People p1(16, "p1"), p2(17, "p2"), p3(18, "p3");
94.   UserVector<People> V(3);
95.   V[0] = p1;
96.   V[1] = p2;
97.   V[2] = p3;
98. 
99.   cout << V[0] << V[1] << V[2] << endl;
100. }
101. 
102. int main()
103. {
104.  //装入普通类型
105.  FuncTest1();
106. 
107.  //装入 类对象
108.  FuncTest2();
109. 
110.  system("pause");
111.  return 0;
112. }

在向容器中装入自己定义的类对象时,一定要自己实现拷贝构造函数,否则可能出现浅拷贝的问题。


相关文章
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
存储 C++ 容器
如何将没有复制或移动构造函数的对象放入vector容器
如何将没有复制或移动构造函数的对象放入vector容器
185 0
|
Ubuntu NoSQL Linux
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
647 6
《docker基础篇:3.Docker常用命令》包括帮助启动类命令、镜像命令、有镜像才能创建容器,这是根本前提(下载一个CentOS或者ubuntu镜像演示)、容器命令、小总结
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
273 9
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
存储 C++ 容器
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器1
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
281 5
|
存储 Kubernetes Cloud Native
探索Python编程的奥秘云原生时代的容器编排:Kubernetes入门与实践
【8月更文挑战第30天】本文以浅显易懂的方式,探讨了Python编程的核心概念和技巧。从基础语法到高级特性,再到实际应用案例,逐步引导读者深入理解Python编程的精髓。通过本文的学习,读者将能够掌握Python编程的基本技能,并激发进一步探索的兴趣。
166 14
|
安全 算法 Java
【Java集合类面试二】、 Java中的容器,线程安全和线程不安全的分别有哪些?
这篇文章讨论了Java集合类的线程安全性,列举了线程不安全的集合类(如HashSet、ArrayList、HashMap)和线程安全的集合类(如Vector、Hashtable),同时介绍了Java 5之后提供的java.util.concurrent包中的高效并发集合类,如ConcurrentHashMap和CopyOnWriteArrayList。
【Java集合类面试二】、 Java中的容器,线程安全和线程不安全的分别有哪些?
|
Java 容器
【Java集合类面试一】、 Java中有哪些容器(集合类)?
这篇文章列出了Java中的四大类集合接口:Set、List、Queue和Map,以及它们的常用实现类,如HashSet、TreeSet、ArrayList、LinkedList、ArrayDeque、HashMap和TreeMap。
【Java集合类面试一】、 Java中有哪些容器(集合类)?
|
容器
【Qt 学习笔记】Qt常用控件 | 容器类控件 | Group Box的使用及说明
【Qt 学习笔记】Qt常用控件 | 容器类控件 | Group Box的使用及说明
1591 3