目录
为什么需要类模板?
题目:设计一个数组模板类(Vector),完成对int, float, double 以及任意的自定义类等类型元素进行管理.
思路:
需要注意的地方:
代码段:
Vector.h
Vector.hpp
main.cpp
说明:
学习心得:在类模板实战中,复习了类的默认构造函数,自定义的构造函数,拷贝构造函数,赋值构造函数,析构函数,友元函数,类模板,以及深拷贝,还有cout <<输出运算符重载,+运算符重载,[]下标运算符重载,=赋值运算符重载进一步熟悉,理解深化.今天就到这儿了!
励志标语: 学习代码需要沉淀!
为什么需要类模板?
->有时,有两个或多个类,其功能是相似的,仅仅是数据类型不同,通过类模板来减少代码量.
->类模板用于实现类所需数据的类型参数化
->类模板在表示支持多种数据结构显得特别重要,这些数据结构的表示和算法不受所包含的元素类型的影响
题目:设计一个数组模板类(Vector),完成对int, float, double 以及任意的自定义类等类型元素进行管理.
项目需求:
a.实现自定义的构造函数
b.实现拷贝构造函数
c.实现cout << 操作运算符重载(友元函数)
d.实现下标访问符 [ ] 的重载操作
e.实现 = 操作符重载
思路:
Vector是一个容器,定义一个int 类型的变量 m_len来表示Vector里面的元素个数,定义一个虚拟类型T的指针(* m_base)动态的为Vector中的元素分配空间.
需要注意的地方:
1.模板类定义类对象,必须显示指定类型
2.模板种如果使用了构造函数,则遵守以前的类的构造函数的调用规则
3.继承中父子类和模板类的结合情况:
a.父类一般类,子类是模板类, 和普通继承的玩法类似
b.子类是一般类,父类是模板类,继承时必须在子类里实例化父类的类型参数
c.父类和子类都时模板类时,子类的虚拟的类型可以传递到父类中
4.函数前声明 template <类型形式参数表>
5.类的成员函数前的类限定域说明必须要带上虚拟参数列表
6.返回的变量是模板类的对象时必须带上虚拟参数列表
7.成员函数参数中出现模板类的对象时必须带上虚拟参数列表
8.成员函数内部没有限定
代码段:
Vector.h
#pragma once #includeusing namespace std; template class Vector { public: Vector();//默认构造函数 Vector(int size );//自定义的构造函数,不能在这样定义了,与Vector() 冲突,可以把默认值去掉 Vector(const Vector& object);//拷贝构造函数 T& operator[](int index);//[]运算符重载 Vector& operator=(const Vector& object);//=运算符重载 int getLength();//获取内部存储的元素个数 ~Vector();//析构函数 template //友元函数 friend ostream& operator<<(ostream & out, const Vector & object); private: T* m_base; int m_len; };
Vector.hpp
#include "Vector.h"
template
Vector::Vector()
{
m_len = 0;
m_base = NULL;
}
template
Vector::Vector(int size){//构造函数
//输出调用的函数名
cout << "call默认构造函数" << __FUNCTION__ << endl;
if (size > 0) {
this->m_len = size;
m_base = new T[m_len];
}
}
template//拷贝构造函数
Vector::Vector(const Vector& object){
//输出调用的函数名
cout << "call拷贝构造函数" << __FUNCTION__ << endl;
//根据传入的对象元素个数分配空间
this->m_len = object.m_len;
this->m_base = new T[m_len];
//数据的拷贝
for (int i = 0; i < m_len; i++) {
m_base[i] = object.m_base[i];
}
}
template//[]运算符重载函数
T& Vector::operator[](int index){
return m_base[index];
//相当于: return *(m_base+index)
}
template//赋值构造函数
Vector& Vector::operator=(const Vector& object){
//输出调用的函数名
cout << "call赋值构造函数" << __FUNCTION__ << endl;
//检测是不是对自己赋值
if (this == &object) {
return *this;
}
//如果有必要,需要先释放自己的资源
delete[] m_base;
m_base = NULL;
m_len = 0;
//根据传入的对象元素个数分配空间
this->m_len = object.m_len;
this->m_base =new T[m_len];
for (int i = 0; i < m_len; i++) {
m_base[i] = object.m_base[i];
}
return *this;
}
template
int Vector::getLength(){//获取对象中的元素个数
return m_len;
}
template
Vector::~Vector(){//析构函数
if (m_base) {
delete[] m_base;
m_base = NULL;
m_len = 0;
}
}
template//重载输出运算符函数
ostream& operator<<(ostream& out, const Vector& object){
for (int i = 0; i < object.m_len; i++){
out << object.m_base[i];
}
return out;
}
main.cpp
#include
#include "Vector.hpp"
//#include
using namespace std;
class Student {
public:
Student() {
this->pname = NULL;
this->age = 0;
}
//自定义的构造函数
Student(const char* pname , int age) {
this->age = age;
size_t len = strlen(pname) + 1;
this->pname = new char[len];
strcpy_s(this->pname, len, pname);
}
//拷贝构造函数
Student(const Student& student) {
this->age = student.age;
size_t len = strlen(student.pname) + 1;
this->pname = new char[len];
strcpy_s(pname, len, student.pname);
}
//重载赋值构造函数
Student& operator=(const Student& student) {
//检测是不是对自己赋值
if (this == &student) {
return *this;
}
如果有必要,需要先释放自己的资源
delete[] pname;
pname = NULL;
age = 0;
//深拷贝
size_t len = strlen(student.pname) + 1;
this->pname = new char[len];
strcpy_s(pname, len, student.pname);
//处理其他数据成员
this->age = student.age;
//返回该对象本身的引用,以便做链式连续处理,比如 a = b = c
return *this;
}
const char* getName() {
return pname;
}
~Student() {//析构函数
delete[] pname;
}
friend ostream& operator<<(ostream& out, const Student& student);
private:
//string name;//姓名
char* pname;//姓名
int age; //年龄
};
int main(void) {
Student stu1("Macro", 20);
Student stu2("Rock", 38);
Student stu3;
stu3 = stu2;
Vector studentVevtor(3);
studentVevtor[0] = &stu1;
studentVevtor[1] = &stu2;
studentVevtor[2] = &stu3;
for (int i = 0; i < studentVevtor.getLength(); i++) {
cout << *studentVevtor[i] << endl;
}
cout << "----------" << endl;
cout << *studentVevtor[0] << endl;
cout << *studentVevtor[2] << endl;
//测试默认构造函数
cout << "-----测试默认构造函数-----" << endl;
Vector myVector(10);
cout << "-----for循环实现输出-----" << endl;
for (int i = 0; i < myVector.getLength(); i++) {
myVector[i] = i;
}
for (int i = 0; i < myVector.getLength(); i++) {
cout << myVector[i];
}
cout << endl;
cout << "-----输出重载实现输出-----" << endl;
cout << myVector << endl;
//测试拷贝构造函数
cout << "-----测试拷贝构造函数-----" << endl;
Vector myVector1(myVector);
cout << "-----for循环实现输出-----" << endl;
for (int i = 0; i < myVector1.getLength(); i++) {
myVector1[i] = i;
}
for (int i = 0; i < myVector1.getLength(); i++) {
cout << myVector1[i];
}
cout << endl;
//测试赋值运算符重载
cout << "-----测试赋值运算符重载-----" << endl;
Vector myVector2;//创建对象时会自动调用默认构造函数
myVector2 = myVector1;
for (int i = 0; i < myVector2.getLength(); i++) {
cout << myVector2[i];
}
cout << endl;
return 0;
}
ostream& operator<<(ostream& out, const Student& student)
{
out << student.pname << ":" << student.age;
return out;
}
#include#include "Vector.hpp" //#include using namespace std; class Student { public: Student() { this->pname = NULL; this->age = 0; } //自定义的构造函数 Student(const char* pname , int age) { this->age = age; size_t len = strlen(pname) + 1; this->pname = new char[len]; strcpy_s(this->pname, len, pname); } //拷贝构造函数 Student(const Student& student) { this->age = student.age; size_t len = strlen(student.pname) + 1; this->pname = new char[len]; strcpy_s(pname, len, student.pname); } //重载赋值构造函数 Student& operator=(const Student& student) { //检测是不是对自己赋值 if (this == &student) { return *this; } 如果有必要,需要先释放自己的资源 delete[] pname; pname = NULL; age = 0; //深拷贝 size_t len = strlen(student.pname) + 1; this->pname = new char[len]; strcpy_s(pname, len, student.pname); //处理其他数据成员 this->age = student.age; //返回该对象本身的引用,以便做链式连续处理,比如 a = b = c return *this; } const char* getName() { return pname; } ~Student() {//析构函数 delete[] pname; } friend ostream& operator<<(ostream& out, const Student& student); private: //string name;//姓名 char* pname;//姓名 int age; //年龄 }; int main(void) { Student stu1("Macro", 20); Student stu2("Rock", 38); Student stu3; stu3 = stu2; Vector studentVevtor(3); studentVevtor[0] = &stu1; studentVevtor[1] = &stu2; studentVevtor[2] = &stu3; for (int i = 0; i < studentVevtor.getLength(); i++) { cout << *studentVevtor[i] << endl; } cout << "----------" << endl; cout << *studentVevtor[0] << endl; cout << *studentVevtor[2] << endl; //测试默认构造函数 cout << "-----测试默认构造函数-----" << endl; Vector myVector(10); cout << "-----for循环实现输出-----" << endl; for (int i = 0; i < myVector.getLength(); i++) { myVector[i] = i; } for (int i = 0; i < myVector.getLength(); i++) { cout << myVector[i]; } cout << endl; cout << "-----输出重载实现输出-----" << endl; cout << myVector << endl; //测试拷贝构造函数 cout << "-----测试拷贝构造函数-----" << endl; Vector myVector1(myVector); cout << "-----for循环实现输出-----" << endl; for (int i = 0; i < myVector1.getLength(); i++) { myVector1[i] = i; } for (int i = 0; i < myVector1.getLength(); i++) { cout << myVector1[i]; } cout << endl; //测试赋值运算符重载 cout << "-----测试赋值运算符重载-----" << endl; Vector myVector2;//创建对象时会自动调用默认构造函数 myVector2 = myVector1; for (int i = 0; i < myVector2.getLength(); i++) { cout << myVector2[i]; } cout << endl; return 0; } ostream& operator<<(ostream& out, const Student& student) { out << student.pname << ":" << student.age; return out; }
以上是类模板实战的代码实现.
说明:
类模板在包含头文件时,类的函数定义即原来的.cpp改为.hpp以示区别,在.hpp文件中包含.h文件,在main.cpp中包含.hpp即可.



