C++泛型详解

本文介绍了C++中的泛型编程,包括模板的使用(如函数模板和类模板),以及在实际开发中如何通过STL创建泛型容器和算法。重点展示了模板在实现通用和类型安全代码中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介        ​

        泛型编程是一种使用模板来编写代码的方法,可以让程序员编写与具体数据类型无关的代码。这种方式可以大大提高代码的复用性和灵活性。

        ​编辑C++的泛型编程主要通过模板实现,包括函数模板和类模板。C++泛型就是为了代码能够更好的复用,所以一般的小项目,基本用不到的,大的项目用着会很不错的。泛型编程就是以独立于任何特定类型的方式编写代码,而模板是泛型编程的基础。​

     首先,举个例子:以数字相加为例的,如下代码所示:

template <class T>
     T add(T num1, T num2)
{
    return num1+num2;
}

    虽然这个能够解决那些问题,可是现实中我们很少会采用一种类型的数字相加的,数字类型有整型、浮点、双精度的,这样,我们在程序中,就可以多次使用:

template <class T1,class T2>
float add(T1 num1, T2 num2)
{
     return (float)num1+(float)num2;
}

二、几种常见模板实现

1、定义函数模板(function template)

    函数模板是一个独立于类型的函数,可以产生函数的特定类型版本。

// implementstrcmp-like generic compare function

template<typename T>

int compare(constT &v1, const T &v2)

{

    if (v1 < v2) return -1;

    if (v2 < v1) return 1;

    return 0;

}

     模板定义以关键字template开始,后接尖括号括住的模板形参表。

     模板形参可以是表示类型的类型形参(type parameter),也可以是表示常量表达式的非类型形参(nontype parameter)。上面程序中的T是类型形参。

// compilerinstantiates int compare(const int&, const int&)

cout <<compare(1, 0) << endl;

// compilerinstantiates int compare(const string&, const string&)

string s1 = “hi”,s2 = “world”;

cout <<compare(s1, s2) << endl;

     使用函数模板时,编译器会将模板实参绑定到模板形参。编译器将确定用什么类型代替每个类型形参,用什么值代替每个非类型形参,然后产生并编译(称为实例化)该版本的函数。

    上面的例子中,编译器用int代替T创建第一个版本,用string代替T创建第二个版本。

    函数模板也可以声明为inline。

// inlinespecifier follows template parameter list

template<typename T> inline T min(const T&, const T&);

2、定义类模板(class template)

    在定义的类模板中,使用模板形参作为类型或值的占位符,在使用类时再提供具体的类型或值。

template<typename Type>

 class Queue

{

public:

    Queue();

    Type & front();

    const Type & front() const;

    void push(const Type &);

    void pop();

    bool empty() const;

private:

    // …

};

     与调用函数模板不同,使用类模板时,必须为模板形参显示指定实参。

Queue<int>qi; // Queue that holds ints

Queue<string>qs; // Queue that holds strings

3、模板类型形参

       类型形参由关键字class或typename后接说明符构成。在函数模板形参表中,二者含义相同。typename其实比class更直观,更清楚的指明后面的名字是一个类型名(包括内置类型),而class很容易让人联想到类声明或类定义。

       此外,在使用嵌套依赖类型(nested depended name)时,必须用到typename关键字。

在类的内部可以定义类型成员。如果要在函数模板内部使用这样的类型,必须显示告诉编译器这个名字是一个类型,否则编译器无法得知它是一个类型还是一个值。默认情况下,编译器假定这样的名字指定(静态)数据成员,而不是类型。所以下面这段程序,如果去掉typename关键字,将会出现编译错误。

template<typename Parm, typename U>

Parm fcn(Parm *array,U value)

{

    typename Parm::size_type * p;

}

4、非类型模板形参

     模板形参也可以是非类型形参,在使用时非类型形参由常量表达式代替。

// initializeelements of an array to zero

template<typename T, size_t N>

void array_init(T(&parm)[N])

{

    for (size_t i = 0; i != N; ++i)

        parm[i] = 0;

}

int x[42];

double y[10];

array_init(x); //instantiates array_init(int (&)[42])

array_init(y); //instantiates array_init(double (&)[10])

5、编写泛型程序

       模板代码需要对使用的类型做一些假设,比如上面的compare()要求类型T重载了“<”操作符。所以函数模板内部完成的操作就限制了可用于实例化该函数的类型。

       编写模板代码时,对实参类型的要求应尽可能少。比如compare()函数仅使用了“<”操作符,而没有使用“>”操作符。

6、模板元编程

        模板元编程是一种利用模板来进行编译时计算的技术。你可以编写在编译期间执行的算法,从而在程序运行前就完成复杂的计算。

template <int N>
struct Factorial {
    static const int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static const int value = 1;
};

// 使用
int fac_5 = Factorial<5>::value; // 120

 实践:泛型容器和算法
        在实际开发中,泛型编程最常见的应用是创建泛型容器,如向量、列表、映射等,以及泛型算法,如排序、查找等。
        STL(Standard Template Library)是C++的标准模板库,它提供了一套丰富的泛型容器和算法。利用STL,你可以处理各种数据结构和算法问题,而不必担心具体的数据类型。例子:使用STL的泛型算法。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = {10, 20, 5, 23, 42};
    std::sort(vec.begin(), vec.end());

    for (int num : vec) {
        std::cout << num << " ";
    }
    return 0;
}

        在上面的例子中,std::sort是一个泛型算法,它可以对任何满足迭代器要求的容器进行排序。这里我们使用它对int类型的vector进行排序,但它同样可以用于其他类型的数据。

三、总结

        总之,C++的泛型编程是一种强大的编程范式,通过使用模板,我们可以创建出既通用又类型安全的代码。从简单的函数和类模板到复杂的类型萃取、SFINAE以及模板元编程,泛型编程在C++中的应用广泛且深入。掌握了泛型编程,我们能够编写出更加灵活、可重用的C++代码。

参考资料:

泛型类 (C++/CLI) | Microsoft Learn

https://zhidao.baidu.com/question/691472121253546644.html?fr=wenku&word=c%2B%2B%E6%B3%9B%E5%9E%8B%E7%BC%96%E7%A8%8B&dyTabStr=MCwyLDEsMyw2LDUsNCw3LDgsOQ==

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大王算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值