文章目录
一、什么是类模板?
类模板是对一批仅仅成员数据类型不同的类的抽象,程序员只要为这一批类所组成的整个类家族创建一个类模板,给出一套程序代码,就可以用来生成多种具体的类,(这类可以看作是类模板的实例),从而大大提高编程的效率。
类模板是一个类家族的抽象,它只是对类的描述,编译程序不为类模板(包括成员函数定义)创建程序代码,但是通过对类模板的实例化可以生成一个具体的类以及该具体类的对象。
与函数模板不同的是:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定
其实例化的一般形式是:
类名 <数据类型 1(或数据),数据类型 2(或数据)…> 对象名
例如,Smemory mol;
表示将类模板Smemory的类型参数T全部替换成int 型,从而创建一个具体的类,并生成该具体类的一个对象mol。
二、类模板的具体使用
- 基本语法
- 类模板对象做函数参数
- 类模板和函数模板的区别
- 类模板与继承
- 类模板与友元
- 类模板中成员函数的创建时机
- 类模板中成员函数类外实现
三、代码实现
1. 基本语法
template<class NameType,class AgeType>
class Person
{
public:
Person(NameType name,AgeType age)
{
this->Name=name;
this->Age=age;
}
void showPerson()
{
cout<<"name:"<<this->Name<<" age:"<<this->Age<<endl;
}
public:
NameType Name;
AgeType Age;
};
void test01()
{
//指定NameType 为string类型,AgeType为int类型
Person<string,int> P1("孙悟空",999);
P1.showPerson();
}
2. 类模板对象做函数参数
template<class T1,class T2>
class Person
{
public:
Person(T1 name,T2 age)
{
this->Name=name;
this->Age=age;
}
void showPerson()
{
cout<<"name:"<<this->Name<<" age:"<<this->Age<<endl;
}
public:
T1 Name;
T2 Age;
};
//1、指定传入的类型
void printPerson1(Person<string,int> &p)
{
p.showPerson();
}
void test01()
{
Person<string,int> p("孙悟空",100);
printPerson1(p);
}
//2、参数模板化
template<class T1,class 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> p("猪八戒",65);
printPerson2(p);
}
//3、整个类模板化
template<class T>
void printPerson3(T &p)
{
cout<<"T的类型为:"<<typeid(T).name()<<endl;
p.showPerson();
}
void test03()
{
Person<string,int> p("唐僧",46);
printPerson3(p);
}
3. 类模板和函数模板的区别
// 类模板和函数模板的区别:
// 1、类模板没有自动类型推导使用方式
// 2、类模板在模板参数列表中可以有默认参数
template<class NameType=string,class AgeType=int> //类模板在模板参数列表中可以有默认参数
class Person
{
public:
Person(NameType name,AgeType age)
{
this->Name=name;
this->Age=age;
}
void showPerson()
{
cout<<"name:"<<this->Name<<" age:"<<this->Age<<endl;
}
public:
NameType Name;
AgeType Age;
};
// 1、类模板没有自动类型推导使用方式
void test01()
{
// Person P1("孙悟空",999); 报错, 无法用自动类型推导
Person<string,int> P1("孙悟空",999); //正确,只能用显示指定类型 指定NameType 为string类型,AgeType为int类型
P1.showPerson();
}
//类模板在模板参数列表中可以有默认参数
void test02()
{
Person<> p("猪八戒",998);
p.showPerson();
}
4. 类模板与继承
template<class T>
class Base
{
T m;
};
//class Son:public Base //错误,c++编译需要给子类分配内存,必须知道父类中T的类型才可以向下继承
class Son:public Base<int> //必须指定一个类型
{
};
void test01()
{
Son c;
}
//类模板继承类模板,可以用T2指定父类中的T类型
template<class T1,class T2>
class Son2 :public Base<T2>
{
public:
Son2()
{
cout<<typeid(T1).name()<<endl;
cout<<typeid(T2).name()<<endl;
}
};
void test02()
{
Son2<int,char>child1;
}
5. 类模板与友元
//全局函数类内实现----直接在类内声明友元即可
//全局函数类外实现---需要提前让编译器知道全局函数的存在
template<class T1,class T2>
class Person;
//全局函数类外实现
template<class T1,class T2>
void PrintPerson2(Person<T1,T2> p)
{
cout<<"类外实现-----姓名:"<<p.Name<<"年龄:"<<p.Age<<endl;
}
template<class T1,class T2>
class Person
{
//全局函数类内实现
friend void PrintPerson(Person<T1,T2> p)
{
cout<<"姓名:"<<p.Name<<"年龄:"<<p.Age<<endl;
}
//全局函数类外实现
//加空模块<>参数列表
//如果全局函数 是类外实现,需要让编译器提前知道这个函数的存在
friend void PrintPerson2<>(Person<T1,T2> p);
public:
Person(T1 name,T2 age)
{
this->Name=name;
this->Age=age;
}
private:
T1 Name;
T2 Age;
};
//全局函数在类内实现
void test01()
{
Person<string,int>p("Nie",20);
PrintPerson(p);
}
void test02()
{
Person<string,int>p("Dong",20);
PrintPerson2(p);
}
6. 类模板中成员函数的创建时机
//类模板中成员函数和普通类中成员函数创建时机是有区别的:
// 1、普通类中的成员函数一开始就可以创建
// 2、类模板中的成员函数在调用时才创建
class Person1
{
public:
void showPerson1()
{
cout<<"Person1 show"<<endl;
}
};
class Person2
{
public:
void showPerson2()
{
cout<<"Person2 show"<<endl;
}
};
template<class T>
class MyClass
{
public:
T obj;
//类模板中的成员函数,并不是一开始就创建的,而是在模板调用是再生成
void fun1()
{
obj.showPerson1();
}
void fun2()
{
obj.showPerson2();
}
};
void test01()
{
MyClass<Person1> m;
m.fun1();
// m.fun2(); 编译会出错,说明函数调用才会去创建成员函数
}
7. 类模板中成员函数类外实现
//类模板中成员函数类外实现
template<class T1,class T2>
class Person
{
public:
//成员函数类内声明
Person(T1 name,T2 age);
void showPerson();
public:
T1 Name;
T2 Age;
};
//构造函数 类外实现
template<class T1,class T2>
Person<T1,T2>::Person(T1 name,T2 age)
{
this->Name=name;
this->Age;
}
//成员函数 类外实现
template<class T1,class T2>
void Person<T1,T2>::showPerson()
{
cout<<"姓名:"<<this->Name<<"年龄:"<<this->Age<<endl;
}
void test01()
{
Person<string,int>p("Tom",20);
p.showPerson();
}