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> { // 派生类只接受一个模板参数,但将两个参数传递给基类
    // 实现...
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值