目录
前言
C++泛型编程学习(二)——类模板中已经介绍了如何在一个文件中,把类模板的方法和实现分开,这里主要记录下类模板的声明和定义分别写在头文件中的方法。
类模板实例
功能:实现一个数组模板类,完成对int、char、Teacher类型元素的管理。这时候如何在Teacher类中有指针类型,就会出现深拷贝和浅拷贝的问题。
- main.cpp
#include <iostream>
#include "MyVector.cpp" // 模板类必须包含成".cpp",一直出现错误,可能和是在code block中编译有关
#include <string.h>
using namespace std;
class Teacher
{
public:
friend ostream & operator<<(ostream& out, Teacher &t);
Teacher& operator=(const Teacher& obj)
{
if(m_p != NULL)
{
delete[] m_p;
m_p = NULL;
age = 33;
}
m_p = new char[strlen(obj.m_p)+1];
strcpy(m_p, obj.m_p);
age = obj.age;
return *this;
}
public:
Teacher()
{
age = 33;
m_p = new char[1];
strcpy(m_p, "");
}
// 在构造函数中,对Teacher的指针变量分配内存
Teacher(char* name, int age)
{
this->age = age;
// strcpy(this->name, name);
m_p = new char[strlen(name)];
strcpy(m_p, name);
}
Teacher(const Teacher& obj)
{
m_p = new char[strlen(obj.m_p)+1];
strcpy(m_p, obj.m_p);
age = obj.age;
}
~Teacher()
{
if(m_p != NULL)
{
delete[] m_p; //
m_p = NULL;
}
}
void printT()
{
cout << "name:" << m_p << " " << "age:" << age << endl;
// cout << "name:" << name << endl;
// cout << "age:" << age << endl;
}
protected:
private:
int age;
// char name[32];
char* m_p;
};
ostream & operator<<(ostream& out, Teacher &t)
{
out << t.m_p << " " << "age=" << t.age << endl;
return out;
}
int main()
{
Teacher t1("t1", 31), t2("t2", 32), t3("t3", 33), t4("t4", 34);
myVector<Teacher*> tArray(4);
tArray[0] = &t1;
tArray[1] = &t2;
tArray[2] = &t3;
tArray[3] = &t4;
for(int i=0; i<4; i++)
{
Teacher *tmp = tArray[i];
tmp->printT();
}
return 0;
}
- MyVector.h
#ifndef MYVECTOR_H
#define MYVECTOR_H
#include <iostream>
using namespace std;
template <typename T>
class myVector
{
// friend ostream& operator<< <T>(ostream &out, const myVector &obj);
public:
myVector(int size=0);
myVector(const myVector &obj); // 拷贝构造函数
virtual ~myVector(); // 析构函数
T& operator[](int index);
myVector &operator=(myVector &obj);
int getLen()
{
return m_len;
}
protected:
int m_len;
T *m_space;
private:
};
#endif // MYVECTOR_H
- MyVector.cpp
#include "MyVector.h"
#include <iostream>
using namespace std;
//在本编译器中使用友元失败
//template <typename T>
//ostream & operator<<(ostream &out, const myVector<T> &obj)
//{
// for(int i=0; i<obj.m_len; i++)
// {
// out << obj.m_space[i] << " ";
// }
// return out;
//}
template <typename T>
myVector<T>::myVector(int size)
{
m_space = new T[size];
m_len = size;
}
template <typename T>
myVector<T>::~myVector()
{
if(m_space != NULL)
{
delete [] m_space;
m_space = NULL;
m_len = 0;
}
}
template <typename T>
myVector<T>::myVector(const myVector &obj)
{
// 根据myV1的大小分配内存
m_len = obj.m_len;
m_space = new T[m_len];
for(int i=0; i<obj.m_len; i++)
{
m_space[i] = obj.m_space[i];
}
}
template <typename T>
T& myVector<T>::operator[](int index)
{
return m_space[index];
}
// a3 = a2 = a1
template <typename T>
myVector<T> & myVector<T>::operator=(myVector<T> &obj)
{
// 先把a2的旧的内存释放掉
if(m_space != NULL)
{
delete [] m_space;
m_space = NULL;
m_len = 0;
}
// 根据a1分配内存,拷贝数据
m_len = obj.m_len;
m_space = new T[m_len];
for(int i=0; i<obj.m_len; i++)
{
m_space[i] = obj.m_space[i];
}
return *this; // a2=a1
}
类模板小结
- 模板是C++类型参数化的多态工具。C++提供函数模板和类模板
- 模板定义以模板说明开始。类属参数必须在模板定义中至少出现一次。
- 同一个类属参数可以用于多个模板。
- 类属参数可以用于函数的参数类型、返回类型和声明函数中的变量。
- 模板由编译器根据实际数据类型实例化,生成可执行代码。实例化的函数模板称为模板函数;实例化的类模板称为模板类
- 函数模板可以用多种方式重载。
- 类模板可以在类层次中使用。
总结
实践才能理解的更深刻,这里大概有个运行的程序感觉就够了。
附上《传智播客扫地僧c++基础和进阶课堂讲义.docx》下载地址。