白骑士的C++教学进阶篇 2.3 模板

系列目录

上一篇:白骑士的C++教学进阶篇 2.2 面向对象编程(OOP)

        模板是C++中一个强大的特性,允许编写通用的代码,提高代码的重用性和灵活性。模板分为函数模板和类模板,还包括模板特化。本篇博客将详细介绍这些内容,帮助您深入理解和应用模板编程。

函数模板

        函数模板允许定义通用的函数,不依赖具体的数据类型。通过参数化类型,函数模板可以用于不同类型的参数。

函数模板的定义与使用

        定义一个函数模板使用 ‘template‘ 关键字和模板参数列表。例如,定义一个通用的交换函数:

template <typename T>
void swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

        在这个例子中,‘T‘ 是一个模板参数,可以代表任意类型。使用函数模板交换两个整数和两个字符串,代码如下:

int main() {
    int x = 10, y = 20;

    swap(x, y);

    std::cout << "x: " << x << ", y: " << y << std::endl;
    std::string str1 = "Hello", str2 = "World";

    swap(str1, str2);

    std::cout << "str1: " << str1 << ", str2: " << str2 << std::endl;

    return 0;
}

        在上面的代码中,模板参数 ‘T‘ 分别被推导为 ‘int‘ 和 ‘std::string‘,实现了通用的交换功能。

多个模板参数

        函数模板可以有多个模板参数。例如,定义一个比较函数,返回较大的值:

template <typename T1, typename T2>


auto max(T1 a, T2 b) -> decltype(a > b ? a : b) {

    return a > b ? a : b;
}

        使用该模板函数比较不同类型的值,例如:

int main() {
    int a = 10;
    double b = 20.5;

    std::cout << "Max: " << max(a, b) << std::endl;

    char c = 'A';

    std::cout << "Max: " << max(a, c) << std::endl;

    return 0;
}

        在上面的代码中,模板参数 ‘T1‘ 和 ‘T2‘ 分别被推导为 ‘int‘ 和 ‘double‘,实现了通用的比较功能。

类模板

        类模板允许定义通用的类,不依赖具体的数据类型。通过参数化类型,类模板可以用于不同类型的成员变量和方法。

类模板的定义与使用

        定义一个类模板使用 ‘template‘ 关键字和模板参数列表。例如,定义一个通用的数组类:

template <typename T>


class Array {
private:
    T* data;
    int size;


public:
    Array(int s) : size(s) {
        data = new T[size];
    }

    ~Array() {
        delete[] data;
    }

    T& operator[](int index) {
        return data[index];
    }

    int getSize() const {
        return size;
    }
};

        在这个例子中,‘T‘ 是一个模板参数,可以代表任意类型。使用类模板创建整数数组和字符串数组,例如:

int main() {
    Array<int> intArray(5);

    for (int i = 0; i < intArray.getSize(); i++) {
        intArray[i] = i * 10;
    }

    for (int i = 0; i < intArray.getSize(); i++) {
        std::cout << intArray[i] << std::endl;
    }

    Array<std::string> strArray(3);
    strArray[0] = "Hello";
    strArray[1] = "World";
    strArray[2] = "C++";

    for (int i = 0; i < strArray.getSize(); i++) {
        std::cout << strArray[i] << std::endl;
    }

    return 0;
}

        在上面的代码中,模板参数 ‘T‘ 分别被推导为 ‘int‘ 和 ‘std::string‘,实现了通用的数组类。

多个模板参数

        类模板可以有多个模板参数。例如,定义一个键值对类:

template <typename K, typename V>


class KeyValuePair {
private:
    K key;
    V value;

public:
    KeyValuePair(K k, V v) : key(k), value(v) {}

    K getKey() const {
        return key;
    }

    V getValue() const {
        return value;
    }
};

        使用该类模板创建不同类型的键值对,例如:

int main() {
    KeyValuePair<int, std::string> intStrPair(1, "one");

    std::cout << "Key: " << intStrPair.getKey() << ", Value: " << intStrPair.getValue() << std::endl;

    KeyValuePair<std::string, double> strDoublePair("PI", 3.14);

    std::cout << "Key: " << strDoublePair.getKey() << ", Value: " << strDoublePair.getValue() << std::endl;

    return 0;
}

        在上面的代码中,模板参数 ‘K‘ 和 ‘V‘ 分别被推导为 ‘int‘ 和 ‘std::string‘,实现了通用的键值对类。

模板特化

        模板特化允许为特定的数据类型提供特殊的实现。当通用的模板代码不能满足特定类型的需求时,使用模板特化可以提供优化或特定功能的实现。

全特化

        全特化是为特定类型提供完全不同的实现。例如,定义一个打印模板函数,并为 ‘char*‘ 类型提供特化:

template <typename T>


void print(T value) {
    std::cout << "Generic print: " << value << std::endl;
}


template <>


void print<char*>(char* value) {
    std::cout << "Specialized print: " << value << std::endl;
}

        使用模板函数打印不同类型的值,例如:

int main() {
    print(42);
    print(3.14);
    print("Hello, world!");

    return 0;
}

        在上面的代码中,‘print‘ 模板函数为 ‘char*‘ 类型提供了特化,实现了不同的打印功能。

偏特化

        偏特化是为模板的某些参数提供特定的实现,而其他参数仍然使用通用模板。例如,定义一个通用的数组类模板,并为指针类型提供偏特化:

template <typename T>


class Array {
private:
    T* data;
    int size;

public:
    Array(int s) : size(s) {
        data = new T[size];
    }

    ~Array() {
        delete[] data;
    }

    T& operator[](int index) {
        return data[index];
    }

    int getSize() const {
        return size;
    }
};


// 为指针类型提供偏特化
template <typename T>


class Array<T*> {
private:
    T** data;
    int size;

public:
    Array(int s) : size(s) {
        data = new T*[size];

        for (int i = 0; i < size; i++) {
            data[i] = nullptr;
        }
    }

    ~Array() {
        for (int i = 0; i < size; i++) {
            delete data[i];
        }
        delete[] data;
    }

    T*& operator[](int index) {
        return data[index];
    }

    int getSize() const {
        return size;
    }
};

        使用该模板类创建指针数组,例如:

int main() {
    Array<int*> ptrArray(3);
    for (int i = 0; i < ptrArray.getSize(); i++) {
        ptrArray[i] = new int(i * 10);
    }

    for (int i = 0; i < ptrArray.getSize(); i++) {
        std::cout << *ptrArray[i] << std::endl;
    }

    return 0;
}

        在上面的代码中,模板类 ‘Array‘ 为指针类型提供了偏特化,实现了不同的内存管理。

总结

        模板是C++中一个强大的特性,通过函数模板、类模板和模板特化,程序员可以编写通用、高效的代码,提高代码的重用性和灵活性。理解并熟练掌握模板编程,将大大提高您的编程能力和效率。希望通过本篇博客的介绍,您能更好地理解和应用C++模板,为编写复杂和高效的C++程序打下坚实的基础。

下一篇:白骑士的C++教学进阶篇 2.4 标准模板库(STL)

相关推荐

  1. 骑士C++教学 2.3 模板

    2024-07-12 05:48:01       27 阅读
  2. 骑士C语言教学高级 3.4 C语言中算法

    2024-07-12 05:48:01       20 阅读
  3. 骑士C++教学基础 1.3 控制流

    2024-07-12 05:48:01       22 阅读
  4. 骑士C++教学基础 1.5 数据结构

    2024-07-12 05:48:01       18 阅读
  5. 骑士C++教学附加 5.2 代码规范与最佳实践

    2024-07-12 05:48:01       15 阅读
  6. 骑士C++教学高级 3.2 多线程与并发

    2024-07-12 05:48:01       19 阅读
  7. 骑士PyCharm教学目录

    2024-07-12 05:48:01       17 阅读
  8. 骑士PyCharm教学基础 1.1 PyCharm简介

    2024-07-12 05:48:01       14 阅读
  9. 骑士PyCharm教学基础 1.3 调试与运行

    2024-07-12 05:48:01       14 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 05:48:01       49 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 05:48:01       53 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 05:48:01       42 阅读
  4. Python语言-面向对象

    2024-07-12 05:48:01       53 阅读

热门阅读

  1. python常用命令

    2024-07-12 05:48:01       18 阅读
  2. 微信小程序中的数据通信

    2024-07-12 05:48:01       23 阅读
  3. TypeScript中的交叉类型

    2024-07-12 05:48:01       25 阅读
  4. CUDA编程 - asyncAPI 学习记录

    2024-07-12 05:48:01       21 阅读
  5. Postman脚本炼金术:高级数据处理的秘籍

    2024-07-12 05:48:01       21 阅读
  6. 使用SOAP与TrinityCore交互(待定)

    2024-07-12 05:48:01       25 阅读
  7. 编程语言如何和计算机交互:深入解析交互机制

    2024-07-12 05:48:01       21 阅读