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;
}

模板的目的就是代码重用,既然链表和数组的逻辑结构是一样的,那就把它们改成模板类的形式。目前模板LinkList和Array,是为了兼容各种各样的数据类型,解决的是物理结构问题。接下来把它们再次模板化,是从逻辑角度来考虑的。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 更新操作

感谢浏览,一起学习!

相关推荐
码农小河663 小时前
基于PHP的电商后台蜜罐系统
开发语言·php
starzy19903 小时前
深入理解Scala柯里化函数:函数链式变换
开发语言·scala
Star(up up up)3 小时前
Redis Windows 安装教程:使用Windows 的 Redis 压缩包
redis·笔记·学习·程序人生·云原生·学习方法·改行学it
ShineWinsu3 小时前
对于Qt:QTreeWidget常见属性以及QTreeWidgetItem类的解析
开发语言·c++·qt·gui·客户端·多叉树·qtreewidget
落羽的落羽4 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
总要学点什么4 小时前
第108篇:三维特效-图片轨迹线效果——把贴图滚成一串箭头,想用它的本色反而整条消失
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
乌暮5 小时前
Spring AOP 与 Spring 事务:用大白话彻底理解原理与实践
java·数据库·spring boot·后端·sql·学习·spring
starzy19909 小时前
深入理解Scala隐式值:编译期自动装配
开发语言·后端·scala
布莱克6059 小时前
Swift 条件语句详解:从 if 到 switch 的完整指南
开发语言·ssh·swift·switch·条件语句·guard·if
汉克老师9 小时前
《从C++小白到算法高手:GESP 1—8级成长地图》第一讲:认识GESP——从编程新手到算法探索者
c++·gesp·信息学竞赛·小学生学c++