《c++提高编程》类模板

一、模板

3、类模板

类模板作用:建立一个通用的类,类中的成员数据类型可以不具体定制,用一个虚拟的类型来代表。

1)语法:

template<typename T>

3)类模板和函数模板的区别

主要有两点:

(1)类模板没有自动推导的使用方式

(2)类模板在模板参数列表中可以有默认参数

4)类模板中成员函数创建时机

类模板中成员函数和普通类中成员函数创建时间是有区别的:

普通类中的成员函数一开始就创建了。而类模板中的成员函数调用时才创建

5)类模板作函数参数

类模板实例化出来的对象向函数传参的方式(3种)

(1)指定传入的类型---直接显示对象的数据类型(常用

(2)参数模板化---将对象中的参数变为模板进行传递

查看参数的类型

(3)整个类模板化---将这个对象类型模板化进行传递

6)类模板与继承

当类模板碰到继承时,应注意:

(1)当子类继承的父类是一个类模板时,子类在声明时要指定父类中T的类型

(2)如果不指定,编译器无法给子类分配内存

(3)如果想灵活指定出父类中T的类型,子类也需要变为类模板

7)类模板成员函数的类外实现

8)类模板的分文件的编写

问题:类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到

解决:

方式1:直接包含.cpp文件

方式2:将声明和实现写到同一个文件中,并更名为.hpp,.hpp是约定的名称 并不是强制。

9)类模板与友元

全局函数类内实现:直接在类内声明友元即可。

全局函数类外实现:需要提前让编译器知道全局函数的存在。

10)模板案例:写一个通用数组类 实现以下功能:

1、可以对内置数据类型以及自定义数据类型进行存储

2、将数组中数据存放到堆区

3、构造函数中可以传入数组的容量

4、提供对应的拷贝构造函数以及operator=防止浅拷贝问题

5、尾插法、尾删法

6、通过下标方式访问数组元素

7、可获取数组中当前元素个数以及数组容量

代码:

.hpp文件

//自己的通用数组类
#pragma once
#include<iostream>
using namespace std;
#include<string>

template<class T>
class MyArray {
private:
	T * pAddress;//将数据放在堆中
	int m_Capacity;
	int size;
public:
	MyArray(int capacity)
	{
		cout << "MyArray有参构造调用" << endl;
		this->m_Capacity = capacity;
		this->size = 0;
		this->pAddress = new T[this->m_Capacity];
	}

	//拷贝构造
	MyArray(const MyArray& arr)
	{
		cout << "MyArray拷贝构造调用" << endl;
		this->m_Capacity = arr.m_Capacity;
		this->size = arr.size;
		//this->pAddress = arr.pAddress 在堆区的数据不能直接这样复制
		//深拷贝
		this->pAddress = new T[arr.m_Capacity];
		for (int i = 0; i < arr.size; i++)
		{
			this->pAddress[i] = arr.pAddress[i];
		}
	}

	//重载= 防止浅拷贝 a=b=c时b、c值为空的情况
	MyArray& operator=(const MyArray& arr)
	{
		cout << "MyArray operator=重载调用" << endl;
		//先判断堆区是否有数据 有则先释放
		if (this->pAddress != NULL)
		{
			delete[] this->pAddress;
			this->pAddress = NULL;
			this->m_Capacity = 0;
			this->size = 0;
		}
		//深拷贝
		this->m_Capacity = arr.m_Capacity;
		this->size = arr.size;
		this->pAddress = new T[this->m_Capacity];
		for (int i = 0; i < arr.size; i++)
		{
			this->pAddress[i] = arr.pAddress[i];
		}
		return *this;
	}

	//尾插法:
	void Push_Back(const T &val)
	{
		//判断容量是否已满
		if (this->size == this->m_Capacity)
		{
			cout << "容量已满,无法插入!" << endl;
			return;
		}
		this->pAddress[this->size] = val;
		size++;
	}

	//尾删法
	void Pop_Back()
	{
		//让用户访问不到最后一个元素 即逻辑尾删
		if (this->size == 0)
		{
			cout << "无元素" << endl;
			return;
		}
		this->size--;
	}

	//通过下标的方式访问数组中元素 重载[]符号 注意若要最终返回的元素可以以arr[0]=100 的方式 则需要加&
    T& operator[](int index)
    {
        return this->pAddress[index];
    }

    //返回数组容量
    int get_Capacity()
    {
        return this->m_Capacity;
    }

    //返回数组大小
    int get_Size()
    {
        return this->size;
    }

	//析构
	~MyArray()
	{
		cout << "MyArray析构调用" << endl;
		if (this->pAddress != nullptr)
		{
			delete [] this->pAddress;
			this->pAddress = NULL;
		}
	}
};

.cpp文件

//实现一个通用的数组类
/*
1、可以对内置数据类型以及自定义数据类型进行存储
2、将数组中数据存放到堆区
3、构造函数中可以传入数组的容量
4、提供对应的拷贝构造函数以及operator=防止浅拷贝问题
5、尾插法、尾删法
6、通过下标方式访问数组元素
7、可获取数组中当前元素个数以及数组容量
*/

#include "MyArray.hpp"

void PrintArray(MyArray<int> &arr);

void test01()
{
	MyArray<int>M(5);
	//MyArray<int>arr1(M);//测试拷贝构造函数
	//MyArray<int>arr2(100);
	//arr2 = arr1;//测试=重载
    for (int i = 0; i < 5; i++)
    {
        M.Push_Back(i);
    }
    cout << "M[3]:" << M.operator[](3) << endl;
    PrintArray(M);
    cout << "M的容量:" << M.get_Capacity() << endl;
    cout << "M的大小:" << M.get_Size() << endl;
    MyArray<int>M1(M);
    PrintArray(M1);
    cout << "M1的容量:" << M1.get_Capacity() << endl;
    cout << "M1的大小:" << M1.get_Size() << endl;
    cout << "尾删后" << endl;
    M1.Pop_Back();
    cout << "M1的容量:" << M1.get_Capacity() << endl;
    cout << "M1的大小:" << M1.get_Size() << endl;
}

void PrintArray(MyArray<int> &arr)
{
    for (int i = 0; i<arr.get_Size(); i++)
    {
        cout << arr[i] << endl;
    }
}

//测试自定义数据类型
class Person {
public:
    string m_name;
    int m_age;
    Person(){}
    Person(string name, int age)
    {
        this->m_age = age;
        this->m_name = name;
    }
};

void PrintPerson(MyArray<Person>arr)
{
    for (int i = 0; i < arr.get_Size(); i++)
    {
        cout << "姓名:" << arr[i].m_name << " 年龄:" << arr[i].m_age << endl;
    }
}

void test02()
{
    MyArray<Person> arr(10);
    Person p1("张三",18);
    Person p2("李四",30);
    Person p3("王五",19);
    Person p4("赵六",28);
    Person p5("郑七",27);
    Person p6("孙八",19);
    Person p7("吴九",38);
    Person p8("胡十",28);
    cout << "没插入前容量:" << arr.get_Capacity() << " 大小为:" << arr.get_Size() << endl;
    arr.Push_Back(p1);
    arr.Push_Back(p2);
    arr.Push_Back(p3);
    arr.Push_Back(p4);
    arr.Push_Back(p5);
    arr.Push_Back(p6);
    arr.Push_Back(p7);
    arr.Push_Back(p8);
    cout << "插入后容量:" << arr.get_Capacity() << " 大小为:" << arr.get_Size() << endl;
    PrintPerson(arr);
    
}


int main()
{
    test01();
	test02();
	return 0;
}

运行结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值