模板是C++类型参数化的多态工具。C++提供函数模板和类模板。
模板定义以模板说明开始。类属参数必须在模板定义中至少出现一次。
同一个类属参数可以用于多个模板。
类属参数可用于函数的参数类型、返回类型和声明函数中的变量。
模板由编译器根据实际数据类型实例化,生成可执行代码。实例化的函数。
模板称为模板函数;实例化的类模板称为模板类。
函数模板可以用多种方式重载。
类模板可以在类层次中使用 。
训练题
1) 请设计一个数组模板类( MyVector ),完成对int、char、Teacher类型元素的管理。
需求
设计:
类模板构造函数 拷贝构造函数 << [] 重载=操作符
a2=a1
实现
2) 请仔细思考:
a) 如果数组模板类中的元素是Teacher元素时,需要Teacher类做什么工作
b) 如果数组模板类中的元素是Teacher元素时,Teacher类含有指针属性哪?
结论1: 如果把Teacher放入到MyVector数组中,并且Teacher类的属性含有指针,就是出现深拷贝和浅拷贝的问题。
结论2:需要Teacher封装的函数有:
1) 重写拷贝构造函数
2) 重载等号操作符
3) 重载左移操作符。
理论提高:所有容器提供的都是值(value)语意,而非引用(reference)语意。容器执行插入元素的操作时,内部实施拷贝动作。所以STL容器内存储的元素必须能够被拷贝(必须提供拷贝构造函数)。
实现代码:
MyVector.h
#pragma once
#include <iostream>
using namespace std;
template<typename T>
class MyVector
{
public:
MyVector(int size);
MyVector(const MyVector&obj);
~MyVector();
public:
T& operator[](int index);
MyVector& operator=(const MyVector&obj );
inline int getLen()
{
return m_len;
}
friend ostream& operator<< <T>(ostream&out,const MyVector<T>&obj);
protected:
T *m_space;
int m_len;
};
MyVector.cpp
#include "MyVector.h"
template<typename T>
MyVector<T>::MyVector(int size)
{
m_space = new T[size];
m_len = size;
}
template<typename T>
MyVector<T>::MyVector(const MyVector&obj)
{
m_len = obj.m_len;
m_space = new T[m_len];
for (int i =0;i<m_len;i++)
{
m_space[i] = obj.m_space[i];
}
}
template<typename T>
MyVector<T>::~MyVector()
{
if (m_space!=NULL)
{
delete[] m_space;
m_space = NULL;
m_len = 0;
}
}
template<typename T>
T& MyVector<T>::operator[](int index)
{
return m_space[index];
}
template<typename T>
MyVector<T>& MyVector<T>::operator=(const MyVector&obj)
{
if (m_space!=NULL)
{
delete[] m_space;
m_space = NULL;
m_len = 0;
}
m_len = obj.m_len;
m_space = new T[m_len];
for (int i =0;i<m_len;i++)
{
m_space[i] = obj.m_space[i];
}
return *this;
}
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;
}
MyVectorTest.cpp
#include <iostream>
#include "MyVector.cpp"
using namespace std;
class Teacher
{
public:
Teacher()
{
this->age = 0;
this->name = new char[1];
strcpy(this->name,"");
}
Teacher(int age,char*name)
{
int len = strlen(name)+1;
this->name = new char[len];
this->age = age;
memcpy(this->name,name,len);
}
Teacher(const Teacher&obj)
{
this->age = obj.age;
int len = strlen(obj.name)+1;
this->name = new char[len];
memcpy(this->name,obj.name,len);
}
~Teacher()
{
if (this->name!=NULL)
{
delete[] this->name;
this->name = NULL;
}
}
void printT()
{
cout<<name<<","<<age<<endl;
}
friend ostream& operator<< (ostream&out,const Teacher &obj);
Teacher& operator=(const Teacher &obj)
{
if (this->name!=NULL)
{
delete[] this->name;
this->name = NULL;
}
int len = strlen(obj.name)+1;
this->name = new char[len];
memcpy(this->name,obj.name,len);
this->age = obj.age;
return *this;
}
protected:
private:
int age;
char *name;
};
ostream& operator<< (ostream&out,const Teacher &obj)
{
out<<obj.name<<":"<<obj.age<<endl;
return out;
}
int main00()
{
MyVector<int> myv(10);
for (int i =0;i<myv.getLen();i++)
{
myv[i] = i+1;
cout<<myv[i];
}
cout<<endl;
MyVector<int> myv2 = myv;
for (int i =0;i<myv2.getLen();i++)
{
myv2[i] = i+1;
cout<<myv2[i];
}
cout<<endl;
cout<<myv2<<endl;
MyVector<char> myv3(10);
for (int i =0;i<myv3.getLen();i++)
{
myv3[i] = 'A';
}
cout<<myv3;
Teacher t1(31,"a"),t2(32,"b"),t3(33,"c"),t4(34,"d");
t1 = t2 = t3;;
MyVector<Teacher> myv4(4);
myv4[0] = t1;
myv4[1] = t2;
myv4[2] = t3;
myv4[3] = t4;
for (int i=0;i<4;i++)
{
Teacher tmp = myv4[i];//拷贝构造
tmp.printT();
}
cout<<myv4<<endl;
myv4[0] = myv4[1];
system("pause");
return 0;
}
int main()
{
Teacher t1(31,"a"),t2(32,"b"),t3(33,"c"),t4(34,"d");
MyVector<Teacher*> myv4(5);
myv4[0] = &t1;
myv4[1] = &t2;
myv4[2] = &t3;
myv4[3] = &t4;
myv4[4] = new Teacher(38,"abc");
for (int i=0;i<5;i++)
{
Teacher *tmp = myv4[i];//拷贝构造
tmp->printT();
}
system("pause");
return 0;
}