目录
分类
1)模板类继承普通类(常见)
2)普通类继承模板类的实例版本
3)普通类继承模板类(常见)
4)模板类继承模板类
5)模板类继承模板参数给出的基类(不能是模板类)
一、模板类不继承
(1)代码
#include<iostream>
using namespace std;
//模板类BB
template<class T1,class T2>
class BB
{
public:
T1 m_x;
T2 m_y;
BB(const T1 x,const T2 y):m_x(x),m_y(y){cout<<"调用了BB的构造函数。"<<endl;}
void fun2()const{cout<<"调用了func2()函数:x="<<m_x<<",y="<<m_y<<endl;}
};
int main()
{
BB<int,string>bb(8,"我是一只小猫咪。");
bb.fun2();
return 0;
}
(2)分析
①模板类BB直接实例化,不继承其他类。
(3)运行结果
二、模板类继承普通类
(1)代码
//普通类AA作为基类,BB类作为派生类
#include<iostream>
using namespace std;
//AABB都没有默认的构造函数
//普通类AA
class AA
{
public:
int m_a;
AA(int a):m_a(a){cout<<"调用了AA的构造函数。"<<endl;}
void fun1(){cout<<"调用了func1()函数:m_a="<<m_a<<endl;}
};
//模板类BB
template<class T1,class T2>
class BB:public AA //111111继承普通类
{
public:
T1 m_x;
T2 m_y;
BB(const T1 x,const T2 y,int a):AA(a),m_x(x),m_y(y){cout<<"调用了BB的构造函数。"<<endl;} //222222派生类的构造函数要调用基类的构造函数
void fun2()const{cout<<"调用了func2()函数:x="<<m_x<<",y="<<m_y<<endl;}
};
int main()
{
BB<int,string>bb(8,"我是一只小猫咪。",3);
bb.fun2();
bb.fun1(); //调用基类的func1()函数
return 0;
}
(2)分析
①程序定义了一个普通类AA,模板类BB作为基类继承普通类AA
template<class T1,class T2> //加模板标签
class BB:public AA
②只需要修改派生类BB的构造函数,调用基类AA的构造函数即可;
BB(const T1 x,const T2 y,int a):AA(a),m_x(x),m_y(y)
(3)运行结果
三、普通类继承模板类的实例版本
(1)代码
#include<iostream>
using namespace std;
//AABB都没有默认的构造函数
//模板类BB
template<class T1,class T2>
class BB
{
public:
T1 m_x;
T2 m_y;
BB(const T1 x,const T2 y):m_x(x),m_y(y){cout<<"调用了BB的构造函数。"<<endl;}
void fun2()const{cout<<"调用了func2()函数:x="<<m_x<<",y="<<m_y<<endl;}
};
//普通类AA
class AA:public BB<int,string> //普通类AA继承模板类BB
{
public:
int m_a;
AA(int a,int x,string y):BB(x,y),m_a(a){cout<<"调用了AA的构造函数。"<<endl;} //派生类构造函数调用基类构造函数(初始化列表)
void fun1(){cout<<"调用了func1()函数:m_a="<<m_a<<endl;}
};
int main()
{
AA aa(3,8,"我是一只小猫咪。");
aa.fun1(); //调用派生类函数
aa.fun2(); //调用基类函数
return 0;
}
(2)分析
①普通类AA作为派生类继承模板类BB
AA只是继承BB的某一个实例化版本,普通类继承,没有特殊之处
class AA:public BB<int,string> //不需要加模板标签
②修改派生类AA的构造函数调用基类BB的构造函数即可
AA(int a,int x,string y):BB(x,y),m_a(a)
3)运行结果
四、普通类继承模板类(常见)(模板类含通用类型参数)
(1)代码
#include<iostream>
using namespace std;
//AABB都没有默认的构造函数
//模板类BB
template<class T1,class T2>
class BB
{
public:
T1 m_x;
T2 m_y;
BB(const T1 x,const T2 y):m_x(x),m_y(y){cout<<"调用了BB的构造函数。"<<endl;}
void fun2()const{cout<<"调用了func2()函数:x="<<m_x<<",y="<<m_y<<endl;}
};
//模板类AA
template<class T1,class T2> //11111BB的模板类标签复制下来
class AA:public BB<T1,T2> //22222普通类继承通用模板类
{
public:
int m_a;
AA(int a,T1 x,T2 y):BB<T1,T2>(x,y),m_a(a){cout<<"调用了AA的构造函数。"<<endl;} //333333修改构造函数
void fun1(){cout<<"调用了func1()函数:m_a="<<m_a<<endl;}
};
int main()
{
AA <int,string>aa(3,8,"我是一只小猫咪。"); //4444AA是一个模板类,需要模板标签
aa.fun1();
aa.fun2();
return 0;
}
(2)分析
①普通类AA作为派生类继承模板类BB(非实例化)
要保留BB的通用类型,就需要把AA变成模板类
template<class T1,class T2> //BB的模板类标签复制下来
class AA:public BB<T1,T2> //普通类继承通用模板类
②修改派生类AA的构造函数调用基类BB的构造函数即可
AA(int a,T1 x,T2 y):BB<T1,T2>(x,y),m_a(a)
(3)运行结果
五、模板类继承模板类
(1)代码
#include<iostream>
using namespace std;
//AABB都没有默认的构造函数
//模板类BB
template<class T1,class T2>
class BB
{
public:
T1 m_x;
T2 m_y;
BB(const T1 x,const T2 y):m_x(x),m_y(y){cout<<"调用了BB的构造函数。"<<endl;}
void fun2()const{cout<<"调用了func2()函数:x="<<m_x<<",y="<<m_y<<endl;}
};
//普通类AA
template<class T1,class T2>
class AA:public BB<T1,T2>
{
public:
int m_a;
AA(int a,T1 x,T2 y):BB<T1,T2>(x,y),m_a(a){cout<<"调用了AA的构造函数。"<<endl;}
void fun1(){cout<<"调用了func1()函数:m_a="<<m_a<<endl;}
};
//模板类CC
template<class T,class T1,class T2> //11111111CC类模板标签增加两个通用类型参数
class CC:public BB<T1,T2> //22222222CC类继承BB类
{
public:
T m_a;
CC(const T a,const T1 x,const T2 y):BB<T1,T2>(x,y),m_a(a){cout<<"调用了CC的构造函数。\n"<<endl;} //CC类构造函数调用基类BB构造函数
void fun3(){cout<<"调用了fun3()函数:m_a="<<m_a<<endl;}
};
int main()
{
CC <int,int,string>cc(3,8,"我是一只小猫咪。");
cc.fun3();
cc.fun2();
return 0;
}
(2)分析
①增加一个模板类CC
template<class T>
class CC
{
public:
T m_a;
CC(const T a):m_a(a){cout<<"调用了CC的构造函数。\n"<<endl;}
void fun3(){cout<<"调用了fun3()函数:m_a="<<m_a<<endl;}
};
②模板类CC继承BB
template<class T,class T1,class T2> //CC类模板标签增加两个通用类型参数
class CC:public BB<T1,T2> //CC类继承BB类
②修改派生类CC的构造函数调用基类BB的构造函数即可;
CC(const T a,const T1 x,const T2 y):BB<T1,T2>(x,y),m_a(a)
(3)运行结果
六、模板类继承模板参数给出的基类(不能是模板类)
(1)代码
#include<iostream>
using namespace std;
//普通类AA
class AA
{
public:
AA(){cout<<"调用了AA的构造函数AA()。"<<endl;}
AA(int a){cout<<"调用了AA的构造函数AA(int a)。"<<endl;}
};
//普通类BB
class BB
{
public:
BB(){cout<<"调用了BB的构造函数BB()。"<<endl;}
BB(int a){cout<<"调用了BB的构造函数BB(int a)。"<<endl;}
};
//普通类CC
class CC
{
public:
CC(){cout<<"调用了CC的构造函数CC()。"<<endl;}
CC(int a){cout<<"调用了CC的构造函数CC(int a)。"<<endl;}
};
//模板类DD
template<class T>
class DD
{
public:
DD(){cout<<"调用了DD的构造函数DD()。"<<endl;}
DD(int a){cout<<"调用了DD的构造函数DD(int a)。"<<endl;}
};
//模板类EE
template<class T>
class EE:public T
{
public:
EE():T(){cout<<"调用了EE的构造函数EE()。"<<endl;}
EE(int a):T(a){cout<<"调用了EE的构造函数EE(int a)。"<<endl;}
};
int main()
{
EE<AA>ea1;//AA作为基类
EE<BB>eb1;//BB作为基类
EE<CC>ec1;//CC作为基类
EE<DD<int> >ed1; //DD<int>作为基类,模板类作为基类时,必须明确指出模板类型参数
//EE<DD>ed1; //DD作为基类,错误
return 0;
}
(2)分析
①EE是模板类,有一个通用模板类型参数,在继承时T可以是普通类,也可以是模板类;
②但是在继承模板类的时候需要指明基类的通用类型参数。
EE<DD<int> >ed1; //DD<int>(类名)作为基类,模板类作为基类时,必须明确指出模板类型参数
//EE<DD>ed1; //DD作为基类,错误