C++类模板

01 类模板语法

#include<iostream>
using namespace std;
//类模板

template<class NameType,class AgeType>
class Person
{
public:
	NameType m_Name;
	AgeType m_Age;

public:
	Person(NameType name, AgeType age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	void ShowPerson()
	{
		cout << "name:" << this->m_Name << " age:" << this->m_Age << endl;
	}
};

void _01Test01()
{
	 Person<string, int> p("Tom", 18);//<  >中就相当于模板形参列表
	 p.ShowPerson();
}

void main()
{
	_01Test01();
}

02 类模板与函数模板的区别

//1、类模板没有自动类型推导的使用方式
//2、类模板在模板参数列表中可以有默认类型参数 函数模板不可以使用默认类型参数

#include<iostream>
using namespace std;
#include <string>

//类模板与函数模板的区别
//1、类模板没有自动类型推导的使用方式
//2、类模板在模板参数列表中可以有默认类型参数 函数模板不可以使用默认类型参数
template<class NameType, class AgeType=int>
class _02Person
{
public:
	NameType m_Name;
	AgeType m_Age;

public:
	_02Person(NameType name, AgeType age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	void ShowPerson()
	{
		cout << "name:" << this->m_Name << " age:" << this->m_Age << endl;
	}
};

//1、类模板没有自动类型推导的使用方式
void _02Test01()
{
	//_02Person p("Tom", 19);//报错 类模板中没有自动类型推导

	_02Person<string, int> p("Tom", 19);
	p.ShowPerson();
}

//2、类模板在模板参数列表中可以有默认类型参数 
void _02Test02()
{
	//使类模板参数列表中的AgeType默认等于int
	_02Person<string> p1("Tony", 20);
	p1.ShowPerson();

	_02Person<string, string>p2("Jack", "22");
	p2.ShowPerson();
}

void main()
{
	//_02Test01();
	_02Test02();
}

03 类模板中成员函数的创建时机

//类模板中的成员函数并不是一开始就创建的 而是在模板调用时才创建

#include <iostream>
using namespace std;

//类模板中成员函数的创建时机
//类模板中的成员函数并不是一开始就创建的 而是在模板调用时才创建
class Person1
{
public:
	void showPerson1()
	{
		cout << "调用showPerson1" << endl;
	}
};

class Person2
{
public:
	void showPerson2()
	{
		cout << "调用showPerson2" << endl;
	}
};

template<class T>
class MyClass
{
public:
	T obj;
public:
	void func1()
	{
		obj.showPerson1();
	}

	void func2()
	{
		obj.showPerson2();
	}
};

void _03Test01()
{
	MyClass<Person1> myClass;
	myClass.func1();
	//myClass.func2();//编译报错 说明函数调用时才会去创建成员函数

}

void main()
{
	_03Test01();
}

04 类模板对象做函数参数

//1、指定传入类型

//2、参数模板化

//3、整个类模板化 使用比较广泛

#include<iostream>
using namespace std;
#include<string>

//类模板对象做函数参数
template<class T1,class T2>
class _04Person
{
public:
	T1 m_Name;
	T2 m_Age;

	_04Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	void showPerson()
	{
		cout << "name:" << this->m_Name << " age:" << this->m_Age << endl;
	}

};

//1、指定传入类型
void PrintPerson1(_04Person<string, int>& p)
{
	p.showPerson();
}
void _04Test01()
{
	_04Person<string, int> p("Tom", 19);
	PrintPerson1(p);
}

//2、参数模板化
template<class T1,class T2>
void PrintPerson2(_04Person<T1, T2>& p)
{
	cout << "T1类型:" << typeid(T1).name() <<  endl;
	cout << " T2类型:" << typeid(T2).name() << endl;
	p.showPerson();
}

void _04Test02()
{
	_04Person<string, int> p("Tony", 29);
	PrintPerson2(p);
}

//3、整个类模板化 使用比较广泛'
template<class T>
void PrintPerson3(T& p)
{
	cout << "T的类型为:" << typeid(T).name() << endl;
	p.showPerson();
}
void _04Test03()
{
	_04Person<string, int> p("Jack", 39);
	PrintPerson3(p);
}

void main()
{
	_04Test01();
	_04Test02();
	_04Test03();
}

05 类模板与继承

//当类模板碰到继承时,需要注意以下几点:
//1、当子类继承的父类为类模板时,子类在声明时,必须指定父类中T的类型
//2、如果不指定,编译器无法给子类分配内存
//3、如果想灵活指定出父类中T的类型,子类也需要变为类模板

#include <iostream>
using namespace std;
//当类模板碰到继承时,需要注意以下几点:
//1、当子类继承的父类为类模板时,子类在声明时,必须指定父类中T的类型
//2、如果不指定,编译器无法给子类分配内存
//3、如果想灵活指定出父类中T的类型,子类也需要变为类模板

//类模板与继承
template<class T >
class Base
{
public:
	T m_Member;

};


//如果不指定,编译器无法给子类分配内存
//class Son1:Base//报错 没有指明父类中T的数据类型
class Son1 :Base<int>
{

};


//如果想灵活指定出父类中T的类型,子类也需要变为类模板
template<class T1,class T2>
class Son2 :Base<T1>
{
public:
	T2 m_Member2;

	Son2()
	{
		cout << "T1的类型为:" << typeid(T1).name() << endl;
		cout << "T2的类型为:" << typeid(T2).name() << endl;
	}

};

void _05Test01()
{
	Son2<char, int> s;
}

void main()
{
	_05Test01();
}

06 类模板成员函数类外实现

#include<iostream>
using namespace std;
//类模板成员函数类外实现
template<class T1,class T2>
class Student
{
public:
	T1 m_Name;
	T2 m_Age;

	Student(T1 name, T2 age);

	void showStudent();
};

template<class T1,class T2>
Student<T1, T2>::Student(T1 name, T2 age)
{
	this->m_Name = name;
	this->m_Age = age;
}

template<class T1,class T2>
void Student<T1, T2>::showStudent()
{
	cout << "姓名;" << this->m_Name << " 年龄:" << this->m_Age << endl;
}


void _06Test01()
{
	Student<string, int >s1("Tom", 19);
	s1.showStudent();
}

void main()
{
	_06Test01();
}

07 类模板分文件编写

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

//解决方法:
//方式1:直接包含.cpp源文件
//方式2:将声名和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制

hpp文件:

#pragma once
#include<iostream>
using namespace std;
template<class T1, class T2>
class _07Person
{
public:
	T1 m_Name;
	T2 m_Age;

	_07Person(T1 name, T2 age);

	void showPerson();
};

template<class T1, class T2>
_07Person<T1, T2>::_07Person(T1 name, T2 age)
{
	this->m_Name = name;
	this->m_Age = age;
}


template<class T1, class T2>
void _07Person<T1, T2>::showPerson()
{
	cout << "name:" << this->m_Name << " age:" << this->m_Age << endl;
}
#include<iostream>

using namespace std;

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

//解决方法:
//方式1:直接包含.cpp源文件
//#include"person.cpp"


//方式2:将声名和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制
#include"person.hpp"

void _07Test01()
{
	_07Person<string, int> p("Tom", 18);
	p.showPerson();
}

void main()
{
	_07Test01();

}

08 类模板与友元

#include<iostream>
using namespace std;

//在编写友元函数实现之前还要提前声明类模板
template<class T1, class T2>
class _08Person;

//友元函数类外实现需要在类之前编写实现
template<class T1, class T2>
void showPerson2(_08Person<T1, T2> p)
{
	cout << "name: " << p.m_Name << " age:" << p.m_Age << endl;
}


template<class T1, class T2>
class _08Person
{
	//友元函数类内实现
	friend void showPerson1(_08Person<T1, T2> p)
	{
		cout << "name: " << p.m_Name << " age:" << p.m_Age << endl;
	}

	//友元函数类外实现 还需要加空模板参数列表
	//如果全局函数是类外实现,还需要让编译器提前知道这个函数的存在
	friend void showPerson2<>(_08Person<T1, T2> p);

public:
	T1 m_Name;
	T2 m_Age;

	_08Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

};

void _08Test01()
{
	_08Person<string, int>p("Jerry", 19);

	showPerson1(p);
}

void _08Test02()
{
	_08Person<string, int>p("Jack", 20);

	showPerson2(p);
}

void main()
{
	//_08Test01();
	_08Test02();

}

09 类模板案例-通用数组类封装

MyArray.hpp文件:

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


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

void _09Test01()
{
	MyArray<int> arr1(5);

	for (int i = 0; i < 5; i++)
	{
		arr1.Push_Back(i);
	}

	cout << "arr1的打印输出:" << endl;
	PrintArray(arr1);
}

void _09Test02()
{
	MyArray<string> arr(10);

	arr.Push_Back("小一");
	arr.Push_Back("小二");
	arr.Push_Back("小三");
	arr.Push_Back("小四");
	arr.Push_Back("小五");

	PrintArray(arr);
	cout << "容量" << arr.getCapacity() << endl;
	cout << "数量" << arr.getSize() << endl;
}

void main()
{
	_09Test01();

	_09Test02();
}

测试文件:

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


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

void _09Test01()
{
	MyArray<int> arr1(5);

	for (int i = 0; i < 5; i++)
	{
		arr1.Push_Back(i);
	}

	cout << "arr1的打印输出:" << endl;
	PrintArray(arr1);
}

void _09Test02()
{
	MyArray<string> arr(10);

	arr.Push_Back("小一");
	arr.Push_Back("小二");
	arr.Push_Back("小三");
	arr.Push_Back("小四");
	arr.Push_Back("小五");

	PrintArray(arr);
	cout << "容量" << arr.getCapacity() << endl;
	cout << "数量" << arr.getSize() << endl;
}

void main()
{
	_09Test01();

	_09Test02();
}

补充:

类模板中的静态成员变量

不同的具体类所共享的静态成员变量不同

示例:

#include<iostream>
using namespace std;

//类模板中的静态成员变量
template<class T>
class MyClass10
{
public:
	static int a;
};

//静态成员类外赋值
template<class T>
int MyClass10<T>::a = 0;

void main()
{
	MyClass10<int> m1, m2,m3;

	MyClass10<char> mm1, mm2, mm3;

	m1.a = 10;
	mm1.a = 100;
	cout << "MyClass10<int>: m1:" << m1.a << " m2:" << m2.a << " m3:" << m3.a << endl;
	cout << "MyClass10<char>: mm1:" << mm1.a << " mm2:" << mm2.a << " mm3:" << mm3.a << endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值