C++的泛型编程方式

1.使用类模板创建数组

下面这段代码:是创建一个元素为 T 类型的数组。

 1 #pragma once
 2 
 3 template<class T>
 4 class MyArray
 5 {
 6 public:
 7     //有参构造
 8     MyArray(int capacity)
 9     {
10         mCapacity = capacity;
11         mSize = 0;
12         pAdress = new T[mCapacity];
13     }
14     //拷贝构造
15     MyArray(const MyArray& my1)
16     {
17         this->mCapacity = my1.mCapacity;
18         this->mSize = my1.mSize;
19         this->pAdress = new T[mCapacity];
20         for (int i = 0; i < mSize; i++)
21             pAdress[i] = my1.pAdress[i];
22     }
23     //重载等号操作符
24     MyArray& operator=(const MyArray& my1)
25     {
26         if (this->pAdress != NULL)
27         {
28             delete[] pAdress;
29             this->pAdress = NULL;
30         }
31         this->mCapacity = my1.mCapacity;
32         this->mSize = my1.mSize;
33         this->pAdress = new T[mCapacity];
34         for (int i = 0; i < mSize; i++)
35             pAdress[i] = my1.pAdress[i];
36         return *this;
37     }
38     //重载[]号操作符
39     T& operator[](int index)
40     {
41         return this->pAdress[index];
42     }
43 
44     //尾插法
45     void pushBack(T val)
46     {
47         if (mSize == mCapacity)
48             return;
49         pAdress[mSize] = val;
50         mSize++;
51     }
52     //尾部删除法
53     void popBack()
54     {
55         mSize--;
56     }
57     ~MyArray()
58     {
59         if (this->pAdress)
60         {
61             delete[] pAdress;
62             pAdress = NULL;
63             mCapacity = 0;
64             mSize = 0;
65         }
66     }
67 
68 
69 private:
70     T* pAdress;            //指向数组的指针
71     int mCapacity;
72     int mSize;    
73 };

2.下面这段代码:是利用上面的模板创建了两个数组(一个是基本数据类型,一个是自定义的类型)

  1 #define _CRT_SECURE_NO_WARNINGS
  2 #include<iostream>
  3 using namespace std;
  4 #include"MyArray.hpp"
  5 
  6 //普通类型
  7 void test021()
  8 {
  9     MyArray<char> arr(10);
 10     for (char i = 'a'; i <= 'j'; i++)
 11         arr.pushBack(i);
 12     for (int i = 0; i < 10; i++)
 13         cout << arr[i]<<"  ";
 14 }
 15 
 16 //自定义类型
 17 class person
 18 {
 19 public:
 20     //无参构造
 21     person()
 22     {
 23         this->mName = new char[strlen("undefined!") + 1];
 24         strcpy(this->mName, "undefined!");
 25         mAge = -1;
 26     }
 27     //有参构造
 28     person(char *name, int age)
 29     {
 30         mName = new char[strlen(name) + 1];
 31         strcpy(mName, name);
 32         mAge = age;
 33     }
 34     //拷贝构造
 35     person(const person& p1)
 36     {
 37         mName = new char[strlen(p1.mName) + 1];
 38         strcpy(mName, p1.mName);
 39         mAge = p1.mAge;
 40     }
 41 
 42     //重载等号操作符
 43     person& operator=(const person& p1)
 44     {
 45         if (mName != NULL)
 46         {
 47             delete[] mName;
 48             mName = NULL;
 49         }
 50         mName = new char[strlen(p1.mName) + 1];
 51         strcpy(mName, p1.mName);
 52         mAge = p1.mAge;
 53         return *this;
 54     }
 55     //对 mName的赋值函数
 56     void sendName(const char * ch)
 57     {
 58         if (mName)
 59         {
 60             delete[] mName;
 61             mName = NULL;
 62         }
 63         mName = new char[strlen(ch) + 1];
 64         strcpy(mName, ch);
 65     }
 66     //析构函数
 67      ~person()
 68     {
 69         if (mName)
 70         {
 71             cout << "析构函数" << endl;
 72             delete[] mName;
 73             mName = NULL;
 74         }
 75     }
 76 public:
 77     char *mName;
 78     int mAge;
 79 };
 80 
 81 //自定义类型
 82 void test022()
 83 {
 84     //自定义类型必须提供默认构造函数
 85     MyArray<person> arr(10);
 86     /*for (int i = 0; i < 10; i++)                    //当初写这段代码时,与下面代码的区别是没有 sendName() 这个函数。此时采用这种赋值方式有两个隐患
 87     {                                            //1.因为自定义的类中有无参构造函数,对对象的每个变量进行了赋值。由于其中一个变量是指针,那么此时它就具有了空间指向。
 88         sprintf(arr[i].mName, "%d%dasafqwdqwdqwdsa%d%d", i, i, i + 1, i + 1);        //2.这时直接赋值是对对象的初始化内容进行替换,并没有申请新内存,而此时对象的指针由于经过初始化,具有了
 89         arr[i].mAge = i + 10;                    //固定大小的内存,一旦赋值超出其长度,就会造成内存泄漏。只有当赋值的内存小于初始化长度时,才不会造成错误。
 90     }*/
 91     for (int i = 0; i < 10; i++)
 92     {                                            //这段代码是上段代码的加强版,有了sendName()这个函数,它具有两个功能,
 93         char buf[100];                            //1.它把对象指针原来指向的内存空间先释放了,
 94         sprintf(buf, "%d%dasafqwdqwdqwdsa%d%d", i, i, i + 1, i + 1);    //2.然后再重新申请赋值长度大小的内存,给他进行了赋值。
 95         arr[i].sendName(buf);                //3.由于sprintf()函数的特点,这里得创建一个缓存空间,足够大,将赋值的内容先拷贝进去,然后再把这个内存空间传入sendName()函数。
 96         arr[i].mAge = i + 10;
 97     }
 98     //这两段代码最主要的区别是:
 99         1.第一段赋值代码没有进行原内存的释放,但同时也没有申请新内存,一旦赋值的长度超过其初始化 mName 的内存,就造成了内存泄漏。
100         2.第二段赋值代码增加了一个赋值函数,这个函数具有两个功能,(1)释放 mName 原有的内存,(2)对 mName 进行新内存的动态申请。
101         3.由于这个函数所传参数的限制,以及 sprintf()函数的使用特点,只有设置一个足够大的缓冲内存,将赋值的内容先拷贝进缓冲内存,
102         再把缓冲内存做实参传给赋值函数,实现对 mName 的赋值。
103     /*person p1("john1", 19);
104     person p2("john2", 29);
105     person p3("john3", 39);
106     person p4("john4", 49);
107     person p5("john5", 59);
108     arr[1] = p1;
109     arr.pushBack(p2);
110     cout << "Name:" << arr[0].mName << " Age:" << arr[0].mAge << endl;
111     arr.pushBack(p3);
112     cout << "Name:" << arr[1].mName << " Age:" << arr[1].mAge << endl;*/
113 
114     for (int i = 0; i < 10; i++)
115         cout << "Name:" << arr[i].mName << " Age:" << arr[i].mAge << endl;
116 }
117 
118 int main()
119 {
120     test022();
121     test021();
122 
123     system("pause");
124     return EXIT_SUCCESS;
125 }

 

posted on 2016-08-02 23:21  路之遥_其漫漫  阅读(816)  评论(0)    收藏  举报

导航