模板类继承普通类(常见)
类AA
和模板类BB
的示例代码如下(两个类目前都没有
默认的构造函数):
#include <iostream>
using namespace std;
class AA {
public:
int m_a;
AA(int a):m_a(a) {cout << "AA构造函数" << endl;}
void func1() {cout << "AA::func1, m_a = " << m_a << endl;}
};
template <class T1, class T2>
class BB {
public:
T1 m_x;
T2 m_y;
BB(T1 x, T2 y): m_x(x), m_y(y) {cout << "BB构造函数" << endl;}
void func2() {cout << "BB::func2, m_x = " << m_x << ", m_y = " << m_y << endl;}
};
// AA和BB都没有默认的构造函数
int main() {
BB<int, string> bb(10, "hello");
bb.func2();
return 0;
}
运行结果如下:
BB构造函数
BB::func2, m_x = 10, m_y = hello
现在修改代码,让类BB
继承AA
。需要考虑的是,在继承时,派生类如何构造基类(要在派生类BB
的构造函数的初始化列表中,指明基类的构造函数)。修改后的代码如下:
#include <iostream>
using namespace std;
class AA {
public:
int m_a;
AA(int a):m_a(a) {cout << "AA构造函数" << endl;}
void func1() {cout << "AA::func1, m_a = " << m_a << endl;}
};
template <class T1, class T2>
class BB: public AA {// 需要考虑,继承的时候,派生类如何构造基类。
public:
T1 m_x;
T2 m_y;
// 指明基类的构造函数,AA的构造需要一个参数,从外面传给它。
BB(const T1 x, const T2 y, int a): AA(a), m_x(x), m_y(y) {cout << "BB构造函数" << endl;}
void func2() {cout << "BB::func2, m_x = " << m_x << ", m_y = " << m_y << endl;}
};
int main() {
// 创建bb对象时,增加一个参数,传递给基类AA的构造函数。
BB<int, string> bb(10, "hello", 123);
bb.func2();
bb.func1(); // 调用基类AA的成员函数
return 0;
}
运行效果如下:
AA构造函数
BB构造函数
BB::func2, m_x = 10, m_y = hello
AA::func1, m_a = 123
普通类继承模板类的实例化版本
模板类有很多实例化版本
,供子类继承。现在让AA
继承BB
的<int, string>
实例化版本。示例代码如下:
#include <iostream>
using namespace std;
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 func2() {cout << "BB::func2, m_x = " << m_x << ", m_y = " << m_y << endl;}
};
class AA:public BB<int, string> {// 派生类
public:
int m_a;
AA(int a, int x, string y):BB(x, y), m_a(a) {cout << "AA构造函数" << endl;}
void func1() {cout << "AA::func1, m_a = " << m_a << endl;}
};
int main() {
AA aa(123, 456, "xxxxxxx");
aa.func1();
aa.func2();
return 0;
}
运行效果如下:
BB构造函数
AA构造函数
AA::func1, m_a = 123
BB::func2, m_x = 456, m_y = xxxxxxx
普通类继承模板类(常见)
AA
只继承BB
的某一个实例化版本很多时候功能是不够用的,故需要AA
继承BB
的通用特性。所以要把AA
变成模板类,示例代码如下:
#include <iostream>
using namespace std;
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 func2() {cout << "BB::func2, m_x = " << m_x << ", m_y = " << m_y << endl;}
};
template <class T1, class T2> // 模板类
class AA:public BB<T1, T2> {
public:
int m_a;
// 修改后的构造函数
AA(int a, const T1 x, const T2 y):BB<T1, T2>(x, y), m_a(a) {cout << "AA构造函数" << endl;}
void func1() {cout << "AA::func1, m_a = " << m_a << endl;}
};
int main() {
// AA也是模板类了,需要指定模板参数。
AA<int, string> aa(111, 222, "你好!");
aa.func1();
aa.func2();
return 0;
}
运行结果如下:
BB构造函数
AA构造函数
AA::func1, m_a = 111
BB::func2, m_x = 222, m_y = 你好!
模板类继承模板类
普通类要继承模板类,必须先把自己变成模板类。若派生类本身就是模板类,则增加基类的通用类型参数就可以了。假设现在有一个模板类CC
,示例代码如下:
template <class T>
class CC{
public:
T m_c;
CC(const T c): m_c(c) {cout << "CC构造函数" << endl;}
void func3() {cout << "CC::func3, m_c = " << m_c << endl;}
};
现在模板类CC
要继承模板类BB
,示例代码如下:
#include <iostream>
using namespace std;
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 func2() {cout << "BB::func2, m_x = " << m_x << ", m_y = " << m_y << endl;}
};
// 增加模板参数
template <class T, class T1, class T2>
class CC:public BB<T1, T2>{
public:
T m_c;
// 修改后的构造函数
CC(const T c, const T1 x, const T2 y): BB<T1, T2>(x, y), m_c(c) {cout << "CC构造函数" << endl;}
void func3() {cout << "CC::func3, m_c = " << m_c << endl;}
};
int main() {
CC<int, string, int> cc(100, "你好!", 333);
cc.func3();
cc.func2();
return 0;
}
运行结果如下:
BB构造函数
CC构造函数
CC::func3, m_c = 100
BB::func2, m_x = 你好!, m_y = 333
模板类继承模板参数给出的基类(不能是模板类)
AA
、BB
和CC
都是普通类,DD
是模板类。
EE
是重点,EE
是模板类,有一个通用类型参数T
的模板类。同时EE
还是派生类
,继承的基类
是模板参数T
。也就是说,EE
继承的基类
是不确定
的,可以改变
,可以作为参数
来传递。此外,还可以用模板参数T
调用基类的构造函数
。
示例代码如下:
#include <iostream> // 包含必要的头文件
using namespace std; // 指定缺省的命名空间
class AA { // 普通类
public:
AA() {cout << "constructor AA()" << endl;}
AA(int a) {cout << "constructor AA(int " << a << ")" << endl;}
};
class BB { // 普通类
public:
BB() {cout << "constructor BB()" << endl;}
BB(int b) {cout << "constructor BB(int " << b << ")" << endl;}
};
class CC { // 普通类
public:
CC() {cout << "constructor CC()" << endl;}
CC(int c) {cout << "constructor CC(int " << c << ")" << endl;}
};
template<class T>
class DD { // 模板类
public:
DD() {cout << "constructor DD()" << endl;}
DD(int d) {cout << "constructor DD(int " << d << ")" << endl;}
};
template<class T>
class EE: public T { // 模板类继承模板参数给出的基类T
public:
EE(): T() {cout << "constructor EE()" << endl;}
EE(int e): T(e) {cout << "constructor EE(int "<< e << ")" << endl;}
};
int main()
{
EE<AA> ea1; // AA作为基类
EE<AA> ea2(10); // AA作为基类,10作为参数传递给基类。
EE<BB> eb; // BB作为基类
EE<BB> eb1(20); // BB作为基类,20作为参数传递给基类。
EE<CC> ec; // CC作为基类
EE<CC> ec1(30); // CC作为基类,30作为参数传递给基类。
EE<DD<int>> ed1; // DD<int>作为基类,一定要指出模板类DD的数据类型。
EE<DD<string>> ed2(666); // DD<string>作为基类,666作为参数传递给基类。
}
运行结果如下:
constructor AA()
constructor EE()
constructor AA(int 10)
constructor EE(int 10)
constructor BB()
constructor EE()
constructor BB(int 20)
constructor EE(int 20)
constructor CC()
constructor EE()
constructor CC(int 30)
constructor EE(int 30)
constructor DD()
constructor EE()
constructor DD(int 666)
constructor EE(int 666)
感谢浏览,一起学习!