C++ 模板

C++ 模板是为了实现泛型编程而添加到 C++ 中的一项强大功能。它允许你定义通用的类和通用的函数,从而为泛型编程提供支持。泛型编程是一种技术,其中通用类型被用作算法中的参数,以便它们可以适用于各种数据类型。

模板可以通过以下两种方式表示:

  • 函数模板
  • 类模板

1.png

函数模板:

我们可以为函数定义一个模板。例如,如果我们有一个 add() 函数,我们可以创建 add 函数的不同版本来对整数、浮点数或双精度数进行相加。

类模板:

我们可以为类定义一个模板。例如,可以创建一个用于数组类的类模板,该类可以接受不同类型的数组,如整数数组、浮点数数组或双精度数组。

函数模板

  • 通用函数使用函数模板的概念。通用函数定义了一组可应用于不同类型数据的操作。
  • 函数将操作的数据类型取决于传递的参数的数据类型。
  • 例如,快速排序算法使用通用函数实现,它可以应用于整数数组或浮点数数组。
  • 通过使用关键字 template 可以创建通用函数。模板定义了函数要执行的操作。

函数模板的语法

template < class Ttype> ret_type func_name(parameter_list) 
{ // 函数体. 
} 

其中,Ttype:这是函数所使用的数据类型的占位符名称。它在函数定义内部使用。它只是一个占位符,编译器会自动用实际的数据类型替换它。

class:类关键字用于在模板声明中指定通用类型。

让我们来看一个函数模板的简单示例:

#include <iostream> 
  using namespace std;
  template<class T> T add(T &a, T &b) 
  { 
    T result = a + b; return result; 
  }
int main() 
{ 
  int i = 2; 
  int j = 3; 
  float m = 2.3; 
  float n = 1.2; 
  cout << "Addition of i and j is: " << add(i, j);      cout << '\n'; cout << "Addition of m and n is: " << add(m, n); 
  return 0; 
} 

输出:

Addition of i and j is: 5 
Addition of m and n is: 3.5 

在上面的示例中,我们创建了一个函数模板,它可以对任何类型(整数、浮点数或双精度数)执行加法运算。

具有多个参数的函数模板

我们可以使用逗号将模板函数中的多个泛型类型分隔开来,从而在模板函数中使用多个泛型类型。

语法

template<class T1, class T2,.....> 
return_type function_name (arguments of type T1, T2....) 
{ 
// 函数体. 
} 

在上述语法中,我们可以看到模板函数可以接受任意数量的不同类型的参数。

让我们来看一个简单的示例:

#include <iostream> using namespace std;

template<class X,class Y> void fun(X a,Y b) { std::cout << "Value of a is: " << a << std::endl; std::cout << "Value of b is: " << b << std::endl; }

int main() { fun(15,12.3);
kotlinCopy code
return 0;
} 

输出:

Value of a is: 15 
Value of b is: 12.3 

在上面的示例中,我们在模板函数中使用了两个泛型类型,即 X 和 Y。

重载函数模板

我们可以重载通用函数,这意味着重载的模板函数在参数列表上有所不同。

让我们通过一个简单的示例来理解这一点:

#include <iostream> 
using namespace std;
template<class X> void fun(X a) 
{ 
  std::cout << "Value of a is: " << a << std::endl; } 
template<class X,class Y> void fun(X b ,Y c) 
{ 
  std::cout << "Value of b is: " << b << std::endl;     std::cout << "Value of c is: " << c << std::endl; 
} 
int main() 
{ 
  fun(10); 
  fun(20,30.5); 
  return 0; 
} 

输出:

Value of a is: 10 
Value of b is: 20 
Value of c is: 30.5 

在上面的示例中,fun() 函数模板被重载。

通用函数的限制

通用函数对于所有版本的函数执行相同的操作,只是数据类型不同。让我们通过一个无法用通用函数替代的重载函数的简单示例来说明这一点。

让我们通过一个简单的示例来理解这一点:

#include <iostream>
using namespace std;

void fun(double a)
{
    cout << "a的值为:" << a << '\n';
}

void fun(int b)
{
    if (b % 2 == 0)
    {
        cout << "数字是偶数";
    }
    else
    {
        cout << "数字是奇数";
    }
}

int main()
{
    fun(4.6);
    fun(6);
    return 0;
}

输出:

a的值为:4.6
数字是偶数

在上面的例子中,我们重载了普通函数。我们不能重载通用函数,因为这两个函数有不同的功能。第一个函数显示值,第二个函数确定数字是偶数还是奇数。

类模板

类模板可以类似地定义为函数模板。当一个类使用模板的概念时,该类被称为通用类。

语法:

template<class Ttype>
class class_name
{
    // ...
};

Ttype是一个占位符,将在实例化类时确定。我们可以使用逗号分隔的列表定义多个通用数据类型。Ttype 可以在类的内部使用。

现在,我们创建一个类的实例:

class_name<type> ob;

其中,

  • class_name:类的名称。
  • type:类所操作的数据的类型。
  • ob:对象的名称。

让我们看一个简单的例子:

#include <iostream>
using namespace std;

template<class T>
class A
{
public:
    T num1 = 5;
    T num2 = 6;
    void add()
    {
        cout << "num1和num2的和:" << num1 + num2 << endl;
    }
};

int main()
{
    A<int> d;
    d.add();
    return 0;
}

输出:

num1和num2的和:11

在上面的例子中,我们为类 A 创建了一个模板。在 main()函数中,我们创建了类 A的实例,并命名为 d。

类模板多个参数:

我们可以在类模板中使用多个通用数据类型,每个通用数据类型之间用逗号分隔。

语法:

template<class T1, class T2, ......>
class class_name
{
    // 类的主体
};

让我们看一个简单的例子,其中类模板包含两个通用数据类型:

#include <iostream>
using namespace std;

template<class T1, class T2>
class A
{
    T1 a;
    T2 b;
public:
    A(T1 x, T2 y)
    {
        a = x;
        b = y;
    }
    void display()
    {
        cout << "a和b的值分别为:" << a << " ," << b << endl;
    }
};

int main()
{
    A<int, float> d(5, 6.5);
    d.display();
    return 0;
}

输出:

a和b的值分别为:5,6.5

非类型模板参数:

模板可以包含多个参数,除了类型 T 参数外,我们还可以使用非类型参数。除了类型 T 参数外,我们还可以使用其他类型的参数,例如字符串、函数名、常量表达式和内置类型。让我们看下面的例子:

template<class T, int size>
class array
{
    T arr[size]; // 自动数组初始化
};

在上述情况中,非类型模板参数是 size,因此模板将数组的大小作为参数传递。

在创建类的对象时指定参数:

array<int, 15> t1;    // 包含15个整数的数组
array<float, 10> t2;  // 包含10个浮点数的数组
array<char, 4> t3;    // 包含4个字符的数组

让我们看一个非类型模板参数的简单示例:

#include <iostream>
using namespace std;

template<class T, int size>
class A
{
public:
    T arr[size];
    void insert()
    {
        int i = 1;
        for (int j = 0; j < size; j++)
        {
            arr[j] = i;
            i++;
        }
    }

    void display()
    {
        for (int i = 0; i < size; i++)
        {
            cout << arr[i] << " ";
        }
    }
};

int main()
{
    A<int, 10> t1;
    t1.insert();
    t1.display();
    return 0;
}

输出:

1 2 3 4 5 6 7 8 9 10

在上面的例子中,创建了一个包含非类型模板参数 size 的类模板 A。在创建类 A 的对象时指定了模板参数。

要记住的要点

  • C++ 支持一种称为模板的强大特性,用于实现通用编程的概念。
  • 模板允许我们创建一族处理不同数据类型的类或函数。
  • 模板类和函数消除了不同数据类型的代码重复,从而使开发更加简单和快速。
  • 类和函数模板都可以使用多个参数。
  • 模板函数也可以重载。
  • 我们还可以使用非类型参数作为模板参数,例如内置或派生的数据类型。

标签: C++语言, C++语言教程, C++语言技术, C++语言学习, C++语言学习教程, C++语言下载, C++语言开发, C++语言入门教程, C++语言进阶教程, C++语言高级教程, C++语言面试题, C++语言笔试题, C++语言编程思想