页面加载中 . . .

C++模板编程


本篇文章脑图地址

C++模板编程

C++函数模板

函数模板的概念

函数模板是用于生成函数的模板。在编译阶段,编译器会根据函数模板的使用情况创建出函数名相同,参数类型由编译器判断的若干函数。
 通过函数模板创建的函数体相同,不同点在于参数类型。

函数模板的使用

每当在一个编译单元(经过预处理的.cpp文件)中使用了函数模板,则必须在该单元中定义一个与函数模板相对应的函数。
 因此,建议在头文件中对函数模板进行声明定义。

函数模板的声明:

template <typename T> // 其中T表示任意类型,参数类型和返回值都可以指定为T
返回类型 函数名(参数列表);
{
  函数体
}

示例代码

  1. 新建一个头文件template.h,文件内容如下:
    #pragma once
    #ifndef _COMPARE_H
    #define _COMPARE_H
    
    template<typename T>
    bool isEqual(T i, T j);
    
    template<typename T>
    bool isEqual(T i, T j)
    {
    	return i == j;
    }
    
    #endif // !_COMPARE_H
  2. 新建main.cpp,在main.cpp中使用函数模板:
    #include <iostream>
    using namespace std;
    #include "compare.h"
    
    int main(int argc, char *argv[])
    {
        cout << isEqual(1, 1) << endl;
        cout << isEqual(22, 1) << endl;
        cout << isEqual(0.1, 0.2) << endl;
        cout << isEqual(1.0f, 1.0f) << endl;
        cout << isEqual("TTT", "TTT") << endl;
        return 0;
    }
    
  3. 编译运行main.cpp,效果如下
    1
    0
    0
    1
    1

函数模板的特化

函数模板的特化是指在实例化模板时,对特定类型的实参进行特殊处理,即当实参为特定类型时,使用该类型的函数体。
 特化需要为函数模板添加新的定义,方式如下

template <>
返回类型 函数名<具体类型>(参数列表)
{ 
  函数体
}

示例代码

  1. 修改main.cpp文件,修改成如下代码:
    #include <iostream>
    using namespace std;
    #include "compare.h"
    
    int main(int argc, char *argv[])
    {   
        char str1[20] = "Hello";
        char str2[20] = "Hello";
        if (isEqual(str1, str2)) 
        {
            cout << "Equal" << endl;
        }
        else
        {
            cout << "Not Equal" << endl;
        }
        return 0;
    }
  2. 编译运行main.cpp,效果如下
    Not Equal
    为什么两个明明是相同类型和字符数相同的字符串,却返回了Not Equal呢?
  • 原来是isEqual函数模板在比较字符串时,默认使用==运算符,而==运算符比较的是字符串的地址,所以返回了Not Equal
  • 字符串内容比较,应该使用strcmp函数
  1. 修改compare.h文件,添加如下代码:

    template <>
    bool isEqual<char*>(char* s1, char* s2)
    {
    	return (strcmp(s1, s2) == 0);
    }
  2. 编译运行main.cpp,效果如下

    Equal

C++类模板

类模板的概念

类模板是用于生成类的模板。在编译阶段,编译器会根据类模板的使用情况创建出仅有部分成员的数据类型和部分成员函数参数类型不同,其他完全相同的若干类。
 通过类模板,可以尝试写出用于存放不同类型数据的容器。

类模板的使用

类模板的声明

类模板的声明和函数模板的声明类似,只是类模板的声明中包含了一个模板参数列表,用于指定模板参数
类模板的声明如下,其中T代表任意类型,由用户指定

template <typename T,...>
class 类名
{
    类成员
}

类模板的成员函数定义如下,一般类模板也应该写在头文件中

template <typename T,...>
返回类型 类名<T,...>::函数名(参数列表)
{
    函数体
}

实例代码

  1. 编写通用数组类,创建MyArray.h头文件,添加如下代码:

    #pragma once
    #ifndef _MYARRAY_H
    #define _MYARRAY_H
    
    template <typename T>
    class MyArray
    {
    private:
    	T data[20];
    	int len;
    public:
    	MyArray();
    	T indexof(int index);
    	void addValue(T value);
    };
    
    template <typename T>
    MyArray<T>::MyArray() : len(0)
    {
    }
    
    template <typename T>
    T MyArray<T>::indexof(int index)
    {
    	return data[index];
    }
    
    template <typename T>
    void MyArray<T>::addValue(T value)
    {
    	data[len] = value;
    	len++;
    }
    
    #endif // !_MYARRAY_H
  2. 测试整形数组,创建main.cpp源文件,添加如下代码:

    #include <iostream>
    using namespace std;
    #include "MyArray.h"
    
    int main(int argc, char *argv[])
    {   
        MyArray<int> arr;
        for (int i = 0; i < 10; ++i)
        {
            arr.addValue(i);
        }
        for (int j = 0; j < 10; ++j)
        {
            cout << arr.indexof(j) << endl;
        }
        return 0;
    }
  3. 编译并运行程序,输出结果如下:

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  4. 测试浮点型数组,修改main.cpp源文件,代码如下:

    #include <iostream>
    using namespace std;
    #include "MyArray.h"
    
    int main(int argc, char *argv[])
    {   
        MyArray<double> arr;
        for (int i = 0; i < 10; ++i)
        {
            arr.addValue(i+.112f);
        }
        for (int j = 0; j < 10; ++j)
        {
            cout << arr.indexof(j) << endl;
        }
        return 0;
    }
  5. 编译并运行程序,输出结果如下:

    0.112
    1.112
    2.112
    3.112
    4.112
    5.112
    6.112
    7.112
    8.112
    9.112

类模板的特化和偏特化

类模板的特化

类模板的特化是指在实例化类模板时,对特定类型的泛型进行特殊处理,即用户指定特定类型的类模板时,通过特化过类模板生成的类可能于其他的类由完全不同的结构。

 特化类模板需要对整个类模板进行声明定义:

template <>
class 类名<指定类型, 指定类型, ...>
{
    类成员
}
示例代码
  1. 修改MyArray.h头文件,添加如下代码:
    template <>
    class MyArray<double>
    {
    public:
    	MyArray();
    };
    
    MyArray<double>::MyArray()
    {
    	cout << "MyArray<double>::MyArray()" << endl;
    }
  2. 修改main.cpp源文件,添加如下代码:
    其中的main函数内容如下
    MyArray<double> arr;
    return 0;
  3. 编译并运行程序,输出结果如下:
    MyArray<double>::MyArray()

类模板的偏特化

偏特化与特化相似,但是偏特化只对类模板的部分参数进行特化,而不是对整个类模板进行特化。
 偏特化模板是需要对整个类模板进行声明定义:

template <typename T, 不需要特化的泛型, ...>
class 类名<T, 不需要特化的泛型, ...>
{
    类成员
}
示例代码
  1. 新增文件pair.h,内容如下:

    #pragma once
    #ifndef _PAIR_H
    #define _PAIR_H
    
    #include <iostream>
    using namespace std;
    
    template<typename T1, typename T2>
    class Pair
    {
    private:
    	T1 first;
    	T2 second;
    public:
    	Pair();
    };
    
    template <typename T1, typename T2>
    Pair<T1, T2>::Pair()
    {
    	cout << "Pair<T1, T2>::Pair()" << endl;
    }
    
    template <typename T2>
    class Pair<char, T2>
    {
    public:
    	Pair();
    };
    
    template <typename T2>
    Pair<char, T2>::Pair()
    {
    	cout << "Pair<char, T2>::Pair()" << endl;
    }
    #endif // !_PAIR_H
  2. main.cpp文件内容如下:

    #include <iostream>
    using namespace std;
    #include "pair.h"
    
    int main(int argc, char *argv[])
    {   
        Pair<char, int> p1;
        Pair<int, char> p2;
        return 0;
    }
    
  3. 编译并运行程序,输出结果如下:

    Pair<char, T2>::Pair()
    Pair<T1, T2>::Pair()

文章作者: ZhiQ
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ZhiQ !
  目录