类模板练习:可以管理基本数据类型,类元素,类指针
定义类模板
MyVector.h
#pragma once
#include <iostream>
using namespace std;
//先考虑类型int char
template <typename T>
class MyVector
{
friend ostream& operator<< <T>(ostream& out, MyVector& obj);
public:
MyVector(int size = 0);
MyVector(const MyVector& obj1);
~MyVector();
int getLen()
{
return m_len;
}
//重载[] = <<
T& operator[](int index);
MyVector& operator=(MyVector& obj2);
private:
T *m_space;
int m_len;
};
实现类模板成员函数
MyVector.cpp
#include <iostream>
#include "MyVector.h"
using namespace std;
template <typename T>
ostream& operator<<(ostream& out, MyVector<T>& obj)
{
for (int i = 0; i < obj.m_len; i++) {
out << obj.m_space[i] << " ";
}
out << endl;
return out;
}
template <typename T>
MyVector<T>::MyVector(int size)
{
m_len = size;
m_space = new T[m_len];
}
template <typename T>
MyVector<T>::MyVector(const MyVector<T>& obj1) //拷贝构造函数
{
m_len = obj1.m_len;
m_space = new T[m_len];
for (int i = 0; i < m_len; i++) { //复制内容
m_space[i] = obj1.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> //a2=a1
MyVector<T>& MyVector<T>::operator=(MyVector<T>& obj2)
{
if (m_space != NULL) {
delete[] m_space;
m_space = NULL;
m_len = 0;
}
m_len = obj2.m_len;
m_space = new T[m_len];
for (int i = 0; i < m_len; i++) { //复制内容
m_space[i] = obj2.m_space[i];
}
return *this;
}
基本数据类型,类元素,类指针 测试框架
MyVectorMain.cpp
//类模板练习:可以管理基本数据类型,类元素,类指针
//这种多文件的调试在改变代码后有时需要重新生成解决方案再进行调试
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "MyVector.cpp"
using namespace std;
/*//定义一个Teacher类,其对象放入类模板里
class Teacher
{
public:
Teacher()
{
age = 20;
strcpy(name, "");
}
Teacher(int age, const char *name) //出错后这里加const
{
this->age = age;
strcpy(this->name, name);
}
void printT()
{
cout << name << ", " << age << endl;
}
private:
int age;
char name[32]; //预先分配了内存,不会有浅拷贝的问题
};*/
//优化Teacher类 5个点,拷贝构造 析构 重载= <<
class Teacher
{
friend ostream& operator<<(ostream& out, Teacher& obj);
public:
Teacher()
{
age = 0;
pname = NULL;
}
Teacher(int age, const char *name) //还是要加const
{
this->age = age;
if (name != NULL) {
int len = strlen(name);
pname = new char[len + 1];
strcpy(pname, name);
}
}
Teacher(const Teacher& obj) //拷贝构造函数
{
//if (pname != NULL) { //清除旧内存
// delete[] pname;
// pname = NULL;
// age = 0;
//}
age = obj.age;
if (obj.pname != NULL) {
int len = strlen(obj.pname);
pname = new char[len + 1];
strcpy(pname, obj.pname);
}
}
~Teacher()
{
if (pname != NULL) {
delete[] pname;
pname = NULL;
age = 0;
}
}
void printT()
{
cout << pname << ", " << age << endl;
}
Teacher& operator=(Teacher& obj) //函数体和拷贝构造函数几乎一样对吗?
{
if (pname != NULL) { //清除旧内存
delete[] pname;
pname = NULL;
age = 0;
}
age = obj.age;
if (obj.pname != NULL) {
int len = strlen(obj.pname);
pname = new char[len + 1];
strcpy(pname, obj.pname);
}
return *this;
}
private:
int age;
//采取指针的定义,需解决浅拷贝的问题
char *pname;
};
ostream& operator<<(ostream& out, Teacher& obj)
{
out << obj.pname << ", " << obj.age << endl;
return out;
}
int main02()
{ //无法将参数 2 从“const char [3]”转换为“char *”
Teacher t1(25, "t1"), t2(26, "t2"), t3(27, "t3"), t4(28, "t4");
MyVector<Teacher> tarray(5);
tarray[0] = t1;
tarray[1] = t2;
tarray[2] = t3;
tarray[3] = t4;
tarray[4] = tarray[0]; //测试Teacher中重载的=
cout << tarray; //重载的<<,Teacher对象数组在数组类模板中输出成功!!
/*for (int i = 0; i < 4; i++) {
Teacher tmp = tarray[i];
tmp.printT();
}*/
return 0;
}
//以上数据类型为Teacher元素,下面采用Teacher指针
int main()
{
Teacher t1(25, "t1"), t2(26, "t2"), t3(27, "t3"), t4(28, "t4");
MyVector<Teacher *> tarray(5);
tarray[0] = &t1;
tarray[1] = &t2;
tarray[2] = &t3;
tarray[3] = &t4;
tarray[4] = tarray[0];
//cout << tarray; //此时输出的是地址!应该再重载<<?
for (int i = 0; i < 5; i++) { //输出指针类型时采用for循环
Teacher *tmp = tarray[i];
tmp->printT();
}
return 0;
}
int main01()
{
MyVector<int> myv1(10);
for (int i = 0; i < myv1.getLen(); i++) {
myv1[i] = i + 1;
cout << myv1[i] << " ";
}
cout << endl;
MyVector<int> myv2 = myv1;
for (int i = 0; i < myv1.getLen(); i++) {
cout << myv2[i] << " ";
}
cout << endl;
cout << myv2;
return 0;
}
结论1: 如果把Teacher放入到MyVector数组中,并且Teacher类的属性含有指针,就是出现深拷贝和浅拷贝的问题。
结论2:需要Teacher封装的函数有:
- 重写拷贝构造函数
- 重载等号操作符
- 重载左移操作符。
理论提高:所有容器提供的都是值(value)语意,而非引用(reference)语意。容器执行插入元素的操作时,内部实施拷贝动作。所以STL容器内存储的元素必须能够被拷贝(必须提供拷贝构造函数)。
|