C++ —— 模板类与继承

模板类继承普通类(常见)

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

模板类继承模板参数给出的基类(不能是模板类)

AABBCC都是普通类,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)

感谢浏览,一起学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值