C++ —— 模板类扩展

C++ ------ 模板类扩展

模板类的成员模板

结构体中可以有结构体,类中可以有类和成员函数。那么,模板类中也应该可以有模板类模板函数

在类AA中再创建一个模板类模板函数

先创建模板类,代码如下:

cpp 复制代码
#include <iostream>
using namespace std;

template <class T1, class T2>
class AA {
public:    
    T1 m_x;
    T2 m_y;

    AA(const T1 x, const T2 y): m_x(x), m_y(y) {}
    void show() {cout << "AA的show ~ m_x = " << m_x << ", m_y = " << m_y << endl;}

    template <class T>
    class BB{
    public:
        T m_b;
        // 可以用AA的模板参数T1、T2创建成员变量
        T1 m_bx;
        BB() {}
        void show() {cout << "BB的show ~ m_b = " << m_b << ", m_bx = " << m_bx << endl;}
    };
    BB<string> bb; // 对象bb就是类模板AA的成员

    template <typename T> // 再创建一个函数模板,这个T和BB中的T没有关系
    void show(T t) {
        cout << "模板函数show ~ t = " << t << endl;
        cout << "AA ~ m_x = " << m_x << ", m_y = " << m_y << endl;
        bb.show();
    }
};

int main() {
    AA<int, string> aa(123, "你好");
    aa.show();
    aa.bb.m_b = "哈哈";
    aa.bb.m_bx = 666;
    aa.bb.show();
    aa.show<string> ("嘻嘻嘻");

    return 0;
}

运行结果如下:

AA的show ~ m_x = 123, m_y = 你好

BB的show ~ m_b = 哈哈, m_bx = 666

模板函数show ~ t = 嘻嘻嘻

AA ~ m_x = 123, m_y = 你好

BB的show ~ m_b = 哈哈, m_bx = 666

模板类中的成员模板,定义可以写在类的外面。修改后的代码如下:

cpp 复制代码
#include <iostream>
using namespace std;

template <class T1, class T2>
class AA {
public:    
    T1 m_x;
    T2 m_y;

    AA(const T1 x, const T2 y): m_x(x), m_y(y) {}
    void show() {cout << "AA的show ~ m_x = " << m_x << ", m_y = " << m_y << endl;}

    template <class T>
    class BB{
    public:
        T m_b;
        // 可以用AA的模板参数T1、T2创建成员变量
        T1 m_bx;
        BB() {}
        void show();
    };
    BB<string> bb; // 对象bb就是类模板AA的成员

    template <typename T> // 再创建一个函数模板,这个T和BB中的T没有关系
    void show(T t);
};

// 模板类中的成员模板,定义可以写在类的外面。
template <class T1, class T2>
template <class T>
void AA<T1, T2>::BB<T>::show() {
    {cout << "BB的show ~ m_b = " << m_b << ", m_bx = " << m_bx << endl;}
}

template <class T1, class T2>
template <typename T>
void AA<T1, T2>::show(T t) {
    cout << "模板函数show ~ t = " << t << endl;
    cout << "AA ~ m_x = " << m_x << ", m_y = " << m_y << endl;
    bb.show();
}


int main() {
    AA<int, string> aa(123, "你好");
    aa.show();
    aa.bb.m_b = "哈哈";
    aa.bb.m_bx = 666;
    aa.bb.show();
    aa.show<string> ("嘻嘻嘻");

    return 0;
}

运行结果跟之前保持一致:

AA的show ~ m_x = 123, m_y = 你好

BB的show ~ m_b = 哈哈, m_bx = 666

模板函数show ~ t = 嘻嘻嘻

AA ~ m_x = 123, m_y = 你好

BB的show ~ m_b = 哈哈, m_bx = 666

将模板类用作参数

C++的类模板主要是为了解决数据结构的问题。线性表有:链表数组、和队列。以链表数组为例,为了支持任意类型数据,最好的方法就是用类模板来实现,代码如下:

cpp 复制代码
#include <iostream>
using namespace std;

template <class T, int len> // 实际上,链表没有长度的说法,但为了演示,假定有一个长度
class LinkList {
public:
    T* m_head; // 定义链表头节点指针
    int m_len = len; // 指定表长度
    // 链表常用操作
    void insert() {cout << "LinkList 插入操作" << endl;}
    void ddelete() {cout << "LinkList 删除操作" << endl;}
    void update() {cout << "LinkList 更新操作" << endl;}
};

template <class T, int len>
class Array{
public:
    T* m_data;
    int m_len = len;
    void insert() {cout << "Array 插入操作" << endl;}
    void ddelete() {cout << "Array 删除操作" << endl;}
    void update() {cout << "Array 更新操作" << endl;}
};

int main() {

	return 0;
}

模板的目的就是代码重用,既然链表和数组的逻辑结构是一样的,那就把它们改成模板类的形式。目前模板LinkListArray,是为了兼容各种各样的数据类型,解决的是物理结构问题。接下来把它们再次模板化,是从逻辑角度来考虑的。C++支持模板的模板,意思是把模板名当成一种特殊的数据类型。实例化对象的时候,可以用模板签名作为参数,传给模板。示例代码如下:

cpp 复制代码
#include <iostream>
using namespace std;

template <class T, int len> // 实际上,链表没有长度的说法,但为了演示,假定有一个长度
class LinkList {
public:
    T* m_head; // 定义链表头节点指针
    int m_len = len; // 指定表长度
    // 链表常用操作
    void insert() {cout << "LinkList 插入操作" << endl;}
    void ddelete() {cout << "LinkList 删除操作" << endl;}
    void update() {cout << "LinkList 更新操作" << endl;}
};

template <class T, int len>
class Array{
public:
    T* m_data;
    int m_len = len;
    void insert() {cout << "Array 插入操作" << endl;}
    void ddelete() {cout << "Array 删除操作" << endl;}
    void update() {cout << "Array 更新操作" << endl;}
};

// 线性表模板类:其中,tabletype 表示 线性表类型,datatype 表示 线性表数据类型,len 表示 长度
// tabletype 不是一个普通的参数,而是模板,意思是这个参数要填模板名。
// 填什么样的模板名呢?填有两个参数的类模板名。并且,要求类模板的第一个参数是通用类型,第二个是非通用类型。
// 此外,class可以用typename代替,只是class更直观。
// tabletype只是一个模板名,用T1创建对象时,还需要指定具体的数据类型。
// 常见的做法是:具体的数据类型用模板参数从外面传进来
template<template<class, int>class tabletype, class datatype, int len> // 模板参数列表
class LinearList{
public:
    tabletype<datatype, len> m_table; // 创建线性表对象
    void insert() {m_table.insert();}
    void ddelete() {m_table.ddelete();}
    void update() {m_table.update();}
};

int main() {
    // 创建线性表对象,容器类型为链表,链表的数据类型为int,链表长度为20
    LinearList<LinkList, int, 20> a;
    a.insert();
    a.ddelete();
    a.update();

    LinearList<Array, string, 20> b;
    b.insert();
    b.ddelete();
    b.update();

    return 0;
}

运行结果如下:

LinkList 插入操作

LinkList 删除操作

LinkList 更新操作

Array 插入操作

Array 删除操作

Array 更新操作

感谢浏览,一起学习!

相关推荐
Victoria.a4 分钟前
c语言文件操作
c语言·开发语言
冷雨夜中漫步5 分钟前
领域驱动设计(4)—绑定模型与实现
java·开发语言·笔记·后端·设计模式
余道各努力,千里自同风7 分钟前
Js中的Object.entries()
开发语言·前端·javascript
世事如云有卷舒1 小时前
《Rust权威指南》学习笔记(三)
笔记·学习·rust
世事如云有卷舒1 小时前
《Rust权威指南》学习笔记(四)
笔记·学习·rust
鲤籽鲲2 小时前
C# _ 数字分隔符的使用
开发语言·c#
fillwang3 小时前
Python实现Excel行列转换
开发语言·python·excel
北极糊的狐4 小时前
SQL中,# 和 $ 用于不同的占位符语法
java·开发语言
玉带湖水位记录员4 小时前
外观模式——C++实现
c++·外观模式
漫漫不慢.5 小时前
九进制转10进制
java·开发语言