一、 类模板对象当做函数的参数
//第一种方式,直接传入模板对象
void fun(person<string,int>& per)
//类模板传入方式
template <class T1,class T2>
void fun3(person<T1,T2>& per)
//整个类模板化
template <class T>
void fun4(T& per)
二、类模板继承
普通类继承:class son:public father{}
模板类继承:普通子类继承模板类;
格式:class 子类:public 父类<指定类型>
构建对象:和普通对象的构建一样 类名 对象(参数列表);
类模板继承类模板
格式: template<class T1,class T2>
class son: public person<T1,T2> {}
三、类模板成员函数类外实现
在类模板中,函数的声明和定义都应该在h文件或者在mian的cpp中,在类中声明,在类外定义需要加上模板的类限定符
案例:template <class T1,class T2>
class myson :public person<T1, T2>
{public:int display(T1 x);};
//;类内声明 类外实现(模板类成员函数)
template <class T1,class T2>
int myson<T1, T2>::display(T1 x){}
}
小秘密:一般情况下会把定义模板类的文件后缀修改成.hpp的形式。
4.代码:
头文件
#pragma once
#include <iostream>
using namespace std;
template <class T1,class T2>
class person
{
public:
T1 m_name;
T2 m_age;
person(T1 name = "", T2 age = 0)
{
this->m_name = name;
this->m_age = age;
cout << "我是构造" << endl;
}
void personShow()
{
cout << "我是person的show函数" << endl;
}
};
//普通类继承模板类
class son :public person<string, int>
{
public://如果父类真的没有缺省构造,应该怎么办
son(int x):person("10",x)
{
cout << "我是son的构造函数" << endl;
}
void show()
{
cout << "我是son的show()" << endl;
}
};
template <class T1,class T2>
class myson :public person<T1, T2>
{
public:
T1 myname;
myson():person<T1,T2>("1",1)
{
cout << "我是myso的构造" << endl;
}
~myson()
{
cout << "我是myso的析构" << endl;
}
myson(const myson<T1, T2>& s)
{
cout << "我是myso的拷贝构造" << endl;
}
void myshow()
{
//m_name怎么使用才能可以
cout << "我的name = " << myname << "父类的name=" << this->m_name << endl;
}
int display(T1 x);
};
//;类内声明 类外实现(模板类成员函数)
template <class T1,class T2>
int myson<T1, T2>::display(T1 x)
{
cout << "myson<T1, T2>::myname=" << myname << endl;
return 0;
}
.cpp 文件
#include <iostream>
#include "person.h"
#include <string>
using namespace std;
//第一种方式,直接传入模板对象
void fun(person<string, int>& per)
{
per.personShow();
}
//类模板传入方式
template <class T1,class T2>
void fun3(person<T1,T2>& per)
{
per.personShow();
//在函数调用的时候,想看一下传入的T1和T2到底是什么类型
cout << typeid(T1).name() << " " << typeid(T2).name() << endl;
}
//整个类模板化
template <class T>
void fun4(T& per)
{
per.personShow();
cout << typeid(T).name() << endl;
}
int main()
{
person<string,int> danny("danny",10);
//fun(danny);
//fun3(danny);
//需要传入类模板的类型参数string和int
//fun4<person<string,int>>(danny);
//子类继承模板类案例
//son s;
// s.show();
person<string, int > x("dd", 10);
myson<string, int> my;
my.myshow();
my.display("ad");
cout << "hello" << endl;
}
四、 类模板的友元函数
1.类外实现友元函数:
先需要在类内声明函数,声明的时候需要加空模板列表,也就是函数名后<>
其次需要在类外实现,但一定是类的定义前实现,在friend函数声明前需要有函数体。
最后在定义完友元函数后,需要先声明模板类。
2.类内实现模板类的友元函数,和普通友元函数实现一样。
代码:
#include <iostream>
//#include "person.hpp"
using namespace std;
//小番茄:提示工具 vs;
template <class T> class person;
template <class T>
void display1(person<T>& per) {}//类前定义
template <class T>
class person
{
T age;
public:
friend void show(person<T>& per) {
per.age = 123;
cout << "per.age = " << per.age << endl;
}
//需要加空模板的参数列表,必须加尖括号
friend void display1<>(person<T>& per);
};
int main()
{
person<int> per;
show(per);
display1(per);
return 0;
}
//stl vector set list deque map c++11标准
练习:实现一个通用的数组类 ( )
第一点:他需要支持基本数据类型和自定义类型。t* parr,int size,int cap) cap是容量,已经存了多少元素。如果存了6个则cap=6
第二点:通用数组中的数据要放入堆内存(new),需要提供
第三点:需要实现构造 析构 有参构造函数
第四点:需要实现==运算符重载,下标运算符[]重载。
第五点:提供两个函数,可以给数组进行为插和尾删除。
代码:
头文件:
#pragma once
#include <iostream>
#include <cstring>
#include <cstdbool>
using namespace std;
template<class T>
class arr
{
public:
arr();//无参构造
arr(int size)//有参构造
{
this->size = size;
this->cap = 0;
this->parr = new T[this->size];//开辟空间
memset(parr, 0, sizeof(T) * size);//初始化数组
}
~arr();//析构函数
void operator=(const arr& other)//重载运算符号 =
{
this->cap = other.cap;
this->size = other.size;
if (this->parr != NULL)
{
delete[] parr;
}
this->parr = new T[this->size];
memcpy(parr, other.parr, sizeof(T) * size);//内存传输
//this->parr = other.parr; 错误
//for (int i = 0;i < other.cap; ++i)
//{
// this->parr[i] = other.parr[i];
//}
}
bool operator==(const arr& other)//重载运算符号 ==
{
if (this->size == other.size && this->cap == other.cap)//看他们的元素个数,和存储空间是否相等
{
return true;
}
return false;
}
T& operator[](const int size)//重载运算符号 []
{
if (size > this->cap)
{
return parr[0];
}
return parr[size];
}
void push_back(const T& temp);//尾部添加函数
void pop_back();//尾部删除函数
private:
T* parr; //数组的首地址
int size; //整个数组的元素个数
int cap; //数组中已经存了多少元素了
};
template<class T>
arr<T>::arr()//类外实现无参构造
{
this->size = 10;
this->cap = 0;
this->parr = new T[this->size];//开辟空间
}
template<class T>
arr<T>::~arr()//类外实现析构函数
{
}
template<class T>
void arr<T>::push_back(const T& temp) //添加元素的函数
{
if (cap == size)
{
return;
}
parr[++cap] = temp;// cap ++ 和元素存储到数组
}
template<class T>
void arr<T>::pop_back()//直接存储元素的数量 减 1
{
if (cap > 0)
{
cap--;
}
}
.cpp 文件
#include <iostream>
#include "arr.hpp"
void show(arr<int> myarr)//arr 类型的数 myarr
{
for (int j = 0; j < 7;++j)
{
cout << myarr[j] << " ";//重载了, 运算符 [] ,所以可以这样!使用
}
cout << endl;
}
void fun1()
{
arr<int> myarr(10);
for (int i = 0;i < 5;++i)
{
myarr.push_back(i);
}
// myarr[1] = 0;
show(myarr);
arr<int> youarr;
youarr = myarr;
show(youarr);
// cout <<
youarr.pop_back();
show(youarr);
}
int main()
{
fun1();
}