类模板
2022-11-28 本文已影响0人
arkliu
类模板的基本语法
- 类模板必须显示指定类型,无法根据参数值来推导类型变量。
#include <iostream>
using namespace std;
template<class T>
class Person {
public:
T m_id;
T m_age;
Person(T id, T age) {
this->m_age = age;
this->m_id = id;
}
void show() {
cout << "id = "<< m_id << " age = "<< m_age << endl;
}
static void static_show() {
cout << "static_show run.." << endl;
}
};
int main() {
// 类模板必须显示指定类型
Person<int> p(22, 33);
p.show();
p.static_show();
Person<int>::static_show();
return 0;
}
为类模板指定默认的类型
- 默认值要放在最后面
#include <iostream>
using namespace std;
template<class T1, class T2=string>
class AA {
private:
T1 age;
T2 name;
public:
AA(T1 age, T2 name="tom") {
this->age = age;
}
};
int main() {
AA<int>aa1(12);
AA<int,double>aa2(33, 4.56);
return 0;
}
类模板具体化
首先去写 “①全特化”,然后再实现 “②普通类模板”,否则会出现"error: ‘XXX’ is not a class template" 错误。
#include <iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class AA {
private:
T1 m_age;
T2 m_name;
public:
AA(T1 age, T2 name):m_age(age),m_name(name) {
cout <<"类模板构造函数..."<<endl;
}
void show()const;
};
template<class T1, class T2>
void AA<T1,T2>::show() const{
cout <<"类模板show函数..."<<endl;
}
template<>
class AA<int,string> {
private:
int m_age;
string m_name;
public:
AA(int age, string name):m_age(age),m_name(name) {
cout <<"类完全具体化构造函数..."<<endl;
}
void show()const;
};
void AA<int,string>::show() const{
cout <<"类完全具体化show函数..."<<endl;
}
template<class T1>
class AA<T1,string> {
private:
T1 m_age;
string m_name;
public:
AA(T1 age, string name):m_age(age),m_name(name) {
cout <<"类部分具体化构造函数..."<<endl;
}
void show()const;
};
template<class T1>
void AA<T1,string>::show() const{
cout <<"类部分具体化show函数..."<<endl;
}
int main() {
AA<int,double>aa2(33, 4.56);
return 0;
}
类模板派生普通类
#include <iostream>
#include<string>
using namespace std;
template<class T>
class Person {
public:
T m_id;
T m_age;
Person(T id, T age):m_id(id),m_age(age) {
cout <<"Person构造函数运行..."<<endl;
}
void show2() {
cout <<"SubPerson show2 m_id "<<m_id<<" m_age "<<m_age<<endl;
}
};
// 用类定义对象,需要编译器分配内存,所以这里需要确定类型
class SubPerson: public Person<int> {
public:
string m_name;
SubPerson(string name, int id, int age):Person(id,age),m_name(name) {
cout <<"SubPerson构造函数运行..."<<endl;
}
void show1() {
cout <<"SubPerson show1 m_name "<<m_name<<endl;
}
};
int main() {
SubPerson subperson("张三", 12, 22);
subperson.show1();
subperson.show2();
Person<int>subperson2(22, 34);
subperson2.show2();
return 0;
}
类模板派生类模板
#include <iostream>
using namespace std;
template<class T>
class Animal {
public:
T m_age;
void speak() {
cout << m_age <<" is speaking.." << endl;
}
};
template<class T>
class Dog: public Animal<T> {
};
int main() {
Dog<int> Dog;
return 0;
}
模板类继承模板参数给出的基类
#include <iostream>
#include<string>
using namespace std;
class AA {
public:
AA() {cout <<"调用了AA的构造函数AA()"<<endl;}
AA(int a) {cout <<"调用了AA的构造函数AA(int a)"<<endl;}
};
class BB {
public:
BB() {cout <<"调用了BB的构造函数BB()"<<endl;}
BB(int b) {cout <<"调用了BB的构造函数BB(int b)"<<endl;}
};
class CC {
public:
CC() {cout <<"调用了CC的构造函数CC()"<<endl;}
CC(int c) {cout <<"调用了CC的构造函数CC(int c)"<<endl;}
};
template<class T>
class DD {
public:
DD() {cout <<"调用了DD的构造函数DD()"<<endl;}
DD(int d) {cout <<"调用了DD的构造函数DD(int d)"<<endl;}
};
template<class T>
class EE :public T{
public:
EE() {cout <<"调用了EE的构造函数EE()"<<endl;}
EE(int e) {cout <<"调用了EE的构造函数EE(int e)"<<endl;}
};
int main() {
EE<AA>e1;
EE<BB>e2;
EE<CC>e3;
EE<DD<int>>e4;
return 0;
}
类模板类内实现
#include<iostream>
using namespace std;
template<class T1, class T2>
class Person {
public:
T1 m_name;
T2 m_age;
Person(T1 name, T2 age) {
this->m_name = name;
this->m_age = age;
}
void show() {
cout << "age = "<< m_age << " name = "<<m_name << endl;
}
};
int main() {
Person<string, int>p("张三", 33);
p.show();
return 0;
}
类模板类外实现
#include<iostream>
using namespace std;
template<class T1, class T2>
class Person {
public:
T1 m_name;
T2 m_age;
Person(T1 name, T2 age);
void show();
};
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>::show() {
cout << "age = "<< m_age << " name = "<<m_name << endl;
}
int main() {
Person<string, int>p("张三", 33);
p.show();
return 0;
}
类模板和静态成员
#include<iostream>
using namespace std;
template<class T1>
class Person {
public:
static int a;
};
//类外初始化
template<class T1> int Person<T1>::a = 10;
int main() {
Person<int> p1, p2, p3;
Person<char>s1, s2, s3;
p1.a = 33;
s1.a = 44;
cout<<"p1.a = "<<p1.a << " p2.a = "<<p2.a <<" p3.a = "<<p3.a<<endl;
cout<<"s1.a = "<<s1.a << " s2.a = "<<s2.a <<" s3.a = "<<s3.a<<endl;
return 0;
}
image.png
拷贝构造函数模板
#include <iostream>
#include<string>
using namespace std;
template<class T1>
class C2 {
public:
C2() {
cout <<"这里是构造函数"<<endl;
}
template<class T2>
C2(const C2<T2> &c2) {
cout <<"这里是自定义的拷贝构造模板"<<endl;
}
template<class T3>
C2<T1> & operator=(const C2<T3> &c2) {
cout <<"这里是拷贝赋值运算符重载模板"<<endl;
return *this;
}
int id;
};
int main() {
C2<int> c2;
c2.id = 123;
// C2<int>c22(c2); 这里并没有调用拷贝构造
C2<double>c22(c2);
C2<double>c222;
c222 =c2;
return 0;
}
image.png
函数模板分文件编写
public.h
#pragma once
#include<iostream>
using namespace std;
void mySwap(int a, int b); // 普通函数
template<typename T>
void mySwap(T a, T b){// 函数模板
cout <<"mySwap func template runs..."<<endl;
}
template<>
void mySwap(int a, int b);
public.cpp
#include "public.h"
void mySwap(int a, int b) { // 普通函数
cout <<"mySwap normal runs..."<<endl;
}
template<>
void mySwap(int a, int b) { //具体化的函数模板
cout <<"mySwap specific runs..."<<endl;
}
test.cpp
#include <iostream>
#include "public.h"
int main() {
mySwap(1, 1);
mySwap('c', 'd');
mySwap<>(1, 1);
return 0;
}
image.png
返回值类型后置
template<typename A, typename B>
auto add(A a, B b) -> decltype(a+b) {
return a+b;
}
int main() {
int a = 200;
double b = 3.14;
auto ret = add<int, double>(a, b);
auto ret1 = add(a, b);
cout << "ret = "<<ret <<" ret1 = "<<ret1<<endl;
return 0;
}
模板类与友元
非模板友元
#include <iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class AA {
private:
T1 m_x;
T2 m_y;
public:
AA(T1 x, T2 y):m_x(x),m_y(y) {}
// 非模板友元,友元函数不是类模板函数,而是利用模板类参数生成的函数,只能在类内实现
friend void show(AA<T1,T2>&aa) {
cout <<"x = "<<aa.m_x<<" y = "<<aa.m_y<<endl;
}
};
int main() {
AA<int,string>aa(23, "张三");
show(aa);
AA<char,string>bb(44, "lisi");
show(bb);
return 0;
}
约束模板友元(常用)
#include <iostream>
#include<string>
using namespace std;
// 约束模板友元:模板类实例化时候,每个实例化的类对应一个友元函数
template<class T> //第一步:在模板类的定义前面声明友元模板
void show(T &a);
template<class T1, class T2>
class AA {
private:
T1 m_x;
T2 m_y;
public:
AA(T1 x, T2 y):m_x(x),m_y(y) {}
friend void show<>(AA<T1,T2>&aa);// 第二步:在模板类中,再次声明友元函数模板
};
// 非模板友元,友元函数不是类模板函数,而是利用模板类参数生成的函数,只能在类内实现
template<class T>
void show(T &aa) // 第三步:友元函数模板的定义
{
cout <<"通用版本:x = "<<aa.m_x<<" y = "<<aa.m_y<<endl;
}
template<>
void show(AA<int,string>&aa) // 第三步:友元函数具体化版本
{
cout <<"具体化版本<int,string> x = "<<aa.m_x<<" y = "<<aa.m_y<<endl;
}
int main() {
AA<int,string>aa(23, "张三");
show(aa);
AA<char,string>bb(44, "lisi");
show(bb);
return 0;
}
模板类的成员模板
#include <iostream>
#include<string>
using namespace std;
template<class T1, class T2>
class AA {
public:
T1 m_x;
T2 m_y;
AA(T1 x, T2 y):m_x(x),m_y(y) {}
void show() {cout <<"m_x = "<<m_x<<" m_y = "<<m_y<<endl;}
template<class T>
class BB {
public:
T m_a;
T1 m_b;
BB() {};
void show();
};
BB<string>m_bb;
template<class T>
void show(T tt);
};
template<class T1, class T2>
template<class T>
void AA<T1,T2>::BB<T>::show() {
cout <<"m_a = "<<m_a<<" m_b = "<<m_b<<endl;
}
template<class T1, class T2>
template<class T>
void AA<T1,T2>::show(T tt) {
cout <<tt<<endl;
m_bb.show();
}
int main() {
AA<int,string>aa(23, "张三");
aa.show();
aa.m_bb.m_a = "我爱北京天安门";
aa.m_bb.m_b = 33;
aa.m_bb.show();
aa.show("东风快递使命必达");
return 0;
}
image.png
类模板特化
#include <iostream>
#include<string>
#include<map>
using namespace std;
template<class T1, class T2>
class C1 {
public:
C1() {
cout <<"C1的构造函数C1()"<<endl;
}
void fun1() {
cout <<"C1的成员函数void fun1() .."<<endl;
}
static int flag;
};
template<class T1, class T2>
int C1<T1,T2>::flag = 3;
// 成员变量的全特化,成员变量不支持偏特化
template<>
int C1<double,double>::flag = 45;
// 成员函数全特化
template<>
void C1<int, int>::fun1() {
cout <<"C1的成员函数void C1<int, int>::fun1()全特化"<<endl;
}
// 成员函数不支持偏特化
// 整个类模板全特化,这里相对于泛化版来讲,哇暖是两个独立的类,除了名字一样,其他的都是不宜硬的
// 可以有自己的成员方法和变量
template<>
class C1<string,string> {
public:
C1() {
cout <<"C1的全特化构造函数C1()"<<endl;
}
void fun1() {
cout <<"C1 全特化的成员函数void fun1() .."<<endl;
}
void fun2() {
cout <<"C1 全特化的成员函数void fun2() .."<<endl;
}
};
int main() {
C1<int,string>c1;
c1.fun1();
cout << c1.flag<<endl;
cout <<endl;
C1<int,int>c2;
c2.fun1();
cout <<endl;
C1<double, double>c3;
cout << c3.flag<<endl;
cout <<endl;
C1<string,string>c4;
c4.fun1();
return 0;
}
image.png