C++模版

在C++中,我们可以使用函数重载来提高代码的灵活性,比如当实现某些相同的功能时,可以重载不同版本的函数,来根据不同的情况实现对应的操作,但是对于每种类型都需要重载一次。而如果使用模版,就可以使代码不再局限于参数的类型,更好的实现代码复用。

模版分为函数模版和类模版

函数模版

函数模板可以用来创建一个通用的函数,以支持多种不同的形参,避免重载函数的函数体重复设计。

函数模板的声明形式为:

template<typename(或class)T>

<返回类型><函数名>(参数表)

{

}

在这里面,class与typename的作用其实是完全一样的,在最早的时候,使用class来表示其后面的是通用类型,但是由于class这个关键字可能会让人们把模版函数和模版类弄混,所以后来又引入了typename。typename和class都是表示后面的类型是通用类型。

当我们定义好了函数模版后,就可以调用其来实现相关的功能。

函数模版的调用有两种,分别是显示类型推导和隐式类型推导

显示类型推导就是在调用的时候在函数名后标明类型,而隐式类型推导就是不标明类型,根据参数的类型自动推导。

我们在定义函数模版的时候也可以直接指定模版默认类型。

自动推导类型的优先级高于默认类型

手动推导类型的优先级高于自动推导类型

另外要注意的一点是,当使用多个参数的模版时,实际参数的类型得是一样的才可以

如果不一样必须手动推导才可以

因为靠自动推导编译器不知道是什么类型,无法通过编译。

模版的特化:

模板特化可以为模板定义一个或多个特定类型的实现。当模板函数被这些特定类型之一调用时,编译器将使用相应的特化版本而不是通用模板。

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

// 通用模板
template <typename T>
void print(T value) {
    cout << "General template: " << value << endl;
}

// 特化版本,针对 int 类型
template <>
void print<int>(int value) {
    cout << "Specialized template for int: " << value << endl;
}

// 特化版本,针对 const char* 类型
template <>
void print<const char*>(const char* value) {
    cout << "Specialized template for const char*: " << value << endl;
}

int main() {
    print(123);            // 调用特化版本,int
    print("Hello, world"); // 调用特化版本,const char*
    print(123.456);        // 调用通用模板
    return 0;
}

类模版

当我们使用类模版,可以将这个类中的成员变量定义为任意类型的数据。

类模版的定义格式为:

template <classT>

class foo

{

}

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

// 类模板定义
template <class T>
class Box {
private:
    T content;
public:
    void setContent(T value) {
        content = value;
    }
    T getContent() {
        return content;
    }
};

int main() {
    Box<int> intBox;
    intBox.setContent(123);
    cout << "Integer Box Content: " << intBox.getContent() << endl;

    Box<string> stringBox;
    stringBox.setContent("Hello Templates!");
    cout << "String Box Content: " << stringBox.getContent() << endl;

    return 0;
}

在上面的代码中,定义了一个类模版,并且定义了两个类,这两个类的成员变量分别为int和string

也可以定义其他数据结构比如栈或者队列的存储类型。

需要注意的是,函数模板可以使用隐式类型推导,但类模板不可以,必须是显示推导,所以在定义模版的时候,必须指定类型,即便是无参构造也要指定。

类模版的继承

类模板也可以参与继承,可以定义一个基于模板的类(父类),然后让其他模板类(子类)继承自这个父类模板。

复制代码
template <typename T>
class Base {
public:
    void baseMethod() {
        // 基类方法实现
    }
};

template <typename T>
class Derived : public Base<T> { // 注意这里
public:
    void derivedMethod() {
        // 派生类方法实现
    }
};

排成类模版从具体化的基类模板继承

派生类模板不仅可以从一个泛型基类模板继承,还可以从一个特定类型的基类模板实例(即模板特化)继承。

复制代码
template <>
class Base<int> {
    // 对 int 类型的特化版本
};

template <typename T>
class Derived : public Base<int> { // 继承自 Base<int>
    // 实现...
};

使用不同的模版参数继承

派生类模板可以使用和基类模板不同的模板参数,甚至可以根据派生类的模板参数来指定基类的模板参数。

复制代码
template <typename T, typename U>
class Base {
    // 基类模板,接受两种类型的模板参数
};

template <typename T>
class Derived : public Base<T, int> { // 派生类只接受一个模板参数,但将两个参数传递给基类
    // 实现...
};
相关推荐
晓晓hh6 小时前
JavaSE学习——迭代器
java·开发语言·学习
Laurence6 小时前
C++ 引入第三方库(一):直接引入源文件
开发语言·c++·第三方库·添加·添加库·添加包·源文件
kyriewen116 小时前
你点的“刷新”是假刷新?前端路由的瞒天过海术
开发语言·前端·javascript·ecmascript·html5
014-code6 小时前
String.intern() 到底干了什么
java·开发语言·面试
421!7 小时前
GPIO工作原理以及核心
开发语言·单片机·嵌入式硬件·学习
蒸汽求职7 小时前
机器人软件工程(Robotics SDE):特斯拉Optimus落地引发的嵌入式C++与感知算法人才抢夺战
大数据·c++·算法·职场和发展·机器人·求职招聘·ai-native
charlee447 小时前
最小二乘问题详解17:SFM仿真数据生成
c++·计算机视觉·sfm·数字摄影测量·无人机航测
摇滚侠7 小时前
JAVA 项目教程《苍穹外卖-12》,微信小程序项目,前后端分离,从开发到部署
java·开发语言·vue.js·node.js
Tanecious.7 小时前
蓝桥杯备赛:Day4-P9749 公路
c++·蓝桥杯
@insist1237 小时前
网络工程师-生成树协议(STP/RSTP/MSTP)核心原理与应用
服务器·开发语言·网络工程师·软考·软件水平考试