栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

类模板实战

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

类模板实战

目录

为什么需要类模板?

题目:设计一个数组模板类(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
#include 

using 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;
}

 以上是类模板实战的代码实现.

说明:

类模板在包含头文件时,类的函数定义即原来的.cpp改为.hpp以示区别,在.hpp文件中包含.h文件,在main.cpp中包含.hpp即可.

学习心得:在类模板实战中,复习了类的默认构造函数,自定义的构造函数,拷贝构造函数,赋值构造函数,析构函数,友元函数,类模板,以及深拷贝,还有cout <<输出运算符重载,+运算符重载,[]下标运算符重载,=赋值运算符重载进一步熟悉,理解深化.今天就到这儿了!

励志标语: 学习代码需要沉淀!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/993651.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号