- 直接上案例:
#include <iostream>
#include <cstring>
using namespace std;
template<class typeName , class typeAge>
class Person
{
public:
Person(typeName name, typeAge age)
{
m_name = name;
m_age = age;
}
public:
void showPerson()
{
cout << "name:" << m_name <<" age: " << m_age << endl;
}
typeName m_name;
typeAge m_age;
};
void test01()
{
//指定typeName为string类型,typeAge为int类型
Person<string,int> p1("张三", 23);
p1.showPerson();
}
int main(void)
{
test01();
return 0;
}
- 类模板和函数模板的区别
1:类模板没有自动类型推导的使用方式
2:类模板在模板参数列表中可以有默认值
示例:
#include <iostream>
#include <cstring>
using namespace std;
//template<class typeName , class typeAge>//验证类模板没有自动类型推导
//类模板参数列表中好像不能先初始化第一个类型
template<class typeAge , class typeName = string>//验证类模板在模板参数列表中可以有默认值
class Person
{
public:
Person(typeName name, typeAge age)
{
this->m_name = name;
this->m_age = age;
}
public:
void showPerson()
{
cout << "name:" << m_name <<" age: " << m_age << endl;
}
typeName m_name;
typeAge m_age;
};
void test01()
{
//Person p1("张三", 23);//类模板没有自动类型推导
Person<int,string> p1("张三", 12 );
p1.showPerson();
}
void test02()
{
Person<int> p2("李四" , 41);
p2.showPerson();
}
int main(void)
{
test01();
test02();
return 0;
}
- 类模板中成员函数和普通类中成员函数创建时机的区别
普通类中的成员函数一开始就可以创建,类模板成员函数调用时才创建
示例:
#include <iostream>
using namespace std;
class Person1
{
public:
void showPerson1()
{
cout << "Person1" << endl;
}
};
class Person2
{
public:
void showPerson2()
{
cout << "Person2" << endl;
}
};
template<class T>
class myClass
{
public:
T obj;
//类模板中的成员函数,并不是一开始就创建的,而是在模板调用时才生成
void func1()
{
obj.showPerson1();
}
void func2()
{
obj.showPerson2();
}
};
void test01()
{
myClass<Person1> m;
m.func1();
//m.func2();//编译出错,说明函数调用才会去创建成员函数
}
int main(void)
{
test01();
return 0;
}
- 类模板对象作函数参数
三种传入方式:
指定传入类型(直接显示对象的数据类型)
参数模板化(将对象中的参数变为模板进行传递)
整个类模板化(将这个对象类型模板化进行传递)
示例:
#include <iostream>
#include <string.h>
using namespace std;
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age)
{
this->m_name = name;
this->m_age = age;
}
void showPerson()
{
cout << "姓名:" << this->m_name << " 年龄:" << this->m_age << endl;
}
T1 m_name;
T2 m_age;
};
//1.指定传入类型
void printPerson1(Person<string, int> &p)
{
p.showPerson();
}
void test01()
{
Person<string, int> p1("孙悟空",100);
printPerson1(p1);
}
//参数模板化
template <typename T1, typename T2>
void printPerson2(Person<T1, T2> &p)//函数模板能自动类型推导
{
p.showPerson();
cout << "T1的类型为:" << typeid(T1).name() << endl;
cout << "T2的类型为:" << typeid(T2).name() << endl;
}
void test02()
{
Person<string, int> p2("猪八戒",200);
printPerson2(p2);
}
//整个类模板化
template <typename T>
void printPerson3(T &p)
{
p.showPerson();
cout << "T的类型为:" << typeid(T).name() << endl;
}
void test03()
{
Person<string, int> p3("唐僧",300);
printPerson3(p3);
}
int main(void)
{
test01();
test02();
test03();
return 0;
}
- 类模板与继承
注意以下几点:
当子类继承的父类是一个类模板时,子类在声明的时候,要制定出副父类中T的类型;如果不指定编译器将无法给子类分配内存;如果想灵活指定出父类中T的类型,子类也需要为类模板。
示例:
#include <iostream>
#include <string.h>
using namespace std;
template<class T>
class parent
{
T m;
};
//class son1:public parent //错误,必须要知道父类中的T的类型,才能继承给子类
class son1:public parent<int>//缺点:指定了T为int型,没达到模板的效果
{
};
void test01()
{
son1 s1;
}
//如果想灵活指定出父类中T的类型,子类也需要为类模板
template<class T1, class T2>//T1传给子类里的对象
class son2:public parent< T2>//T2传给父类
{
public:
son2()
{
cout << "T1的类型为:" << typeid(T1).name() << endl;
cout << "T2的类型为:" << typeid(T2).name() << endl;
}
T1 obj;
};
void test02()
{
son2<int,char> s2;
}
int main()
{
test01();
test02();
return 0;
}
- 类模板成员函数类外实现
#include <iostream>
#include <cstring>
using namespace std;
template<class T1 , class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_name;
T2 m_age;
};
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
this->m_name = name;
this->m_age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
cout << "name:" << this->m_name <<" age: " << this->m_age << endl;
}
void test01()
{
Person<string,int> p1("张三", 23);
p1.showPerson();
}
int main(void)
{
test01();
return 0;
}
- 类模板分文件编写
问题:类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制。
.h文件
#pragma once //防止头文件重复包含
#include <iostream>
using namespace std;
template<class T1 , class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_name;
T2 m_age;
};
.cpp文件
#include <iostream>
#include "Person.h"
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
this->m_name = name;
this->m_age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
cout << "name:" << this->m_name <<" age: " << this->m_age << endl;
}
.hpp文件(实际就是将.cpp和.h文件和在一起)
#pragma once //防止头文件重复包含
#include <iostream>
using namespace std;
template<class T1 , class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_name;
T2 m_age;
};
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
this->m_name = name;
this->m_age = age;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
cout << "name:" << this->m_name <<" age: " << this->m_age << endl;
}
源文件
#include <iostream>
//#include "Person.cpp"//第一种方式:直接包含源文件把.h改为.cpp编译就不会报错了
//第二种方式:将.h和.cpp文件写在一起,命名为.hpp文件
#include "Person.hpp"
using namespace std;
void test01()
{
Person<string,int> p1("张三", 23);
p1.showPerson();
}
int main(void)
{
test01();
return 0;
}
- 类模板与友元
示例:
#include <iostream>
#include <string>
using namespace std;
template<class T1, class T2>
class Person;//告诉编译器等一下会编写这个类
//类外实现必须先让编译器看到有这样一个全局函数存在
template<typename T1, typename T2>
void printPerson2(Person<T1, T2> &p)
{
cout << "类外实现" << "姓名" << p.m_name << "年龄" << p.m_age << endl;
}
template<class T1, class T2>
class Person
{
//全局函数,类内实现
friend void printPerson1(Person<T1, T2> p)
{
cout << "类内实现姓名" << p.m_name << "年龄" << p.m_age << endl;
}
//全局函数类外实现
//加空模板参数列表
friend void printPerson2<>(Person<T1, T2> &p);
public:
Person(T1 name , T2 age)
{
this->m_age = age;
this->m_name = name;
}
private:
T1 m_name;
T2 m_age;
};
//全局函数在类内实现的测试函数
void test01()
{
Person<string , int> p("Tom",20);
printPerson1(p);
}
//全局函数在类外实现的测试函数
void test02()
{
Person<string , int> p("Marry",10);
printPerson2(p);
}
int main(void)
{
test01();
test02();
return 0;
}