首页 > 编程语言 >C++ 编程基础(8)模版 | 8.2、函数模版

C++ 编程基础(8)模版 | 8.2、函数模版

时间:2024-11-18 10:50:11浏览次数:3  
标签:8.2 函数 模版 C++ 实例 参数 template print 模板

文章目录


前言:

C++ 函数模板是一种强大的特性,它允许程序员编写与类型无关的代码。通过使用模板,函数或类可以处理不同的数据类型,而无需重复编写代码。这种机制提高了代码的可重用性和灵活性。本文将详细介绍C++中的函数模板,包括其定义、使用、实例化以及模板的特化。

一、函数模版

1、声明与定义

函数模板的定义以 template 关键字开头,后面跟着一个模板参数列表(用尖括号 < > 包围)。模板参数列表中的参数可以是类型参数,也可以是非类型参数(如整数常量)。以下是一个简单的函数模板示例,用于计算两个值的最大值:

#include <iostream>

// 定义一个函数模板
template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    int intVal1 = 5, intVal2 = 10;
    double doubleVal1 = 5.5, doubleVal2 = 4.4;

    std::cout << "Max of int values: " << max(intVal1, intVal2) << std::endl;
    std::cout << "Max of double values: " << max(doubleVal1, doubleVal2) << std::endl;

    return 0;
}

2、模版参数

除了类型参数(typenameclass 关键字定义),C++ 函数模板还支持非类型参数。非类型参数通常在模板参数列表中定义,可以包括以下几种形式:

  • 整型常量:如int N
  • 枚举常量:如enum E { A, B } e
  • 指针或引用:如int* ptrconst char& c
  • 模板类型:如typename T::value_type

以下是一个简单的示例,展示如何使用非类型参数来创建一个通用的幂运算函数:

#include <iostream>

// 带有非类型参数的模板函数
template <typename T, int N>
T power(T a) {
    T result = 1;
    for (int i = 0; i < N; ++i) {
        result *= a;
    }
    return result;
}

int main() {
    std::cout << "2^3 = " << power<int, 3>(2) << std::endl;      // 输出: 2^3 = 8
    std::cout << "4^2 = " << power<double, 2>(4) << std::endl;   // 输出: 4^2 = 16.0
    return 0;
}

3、模板的实例化

在代码中包含模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。当编译器遇到一个函数模板调用时,它会尝试根据提供的参数类型实例化模板。如果成功,编译器会生成相应的函数代码。这个过程称为模板实例化。常见的三种实例化方法分别是:隐式实例化,显示实例化和模版的特化

3.1、隐式实例化

隐式实例化是指在调用函数模板时,如果没有找到匹配的函数或函数模板,编译器会自动根据传入的参数类型来实例化模板。这种方式不需要程序员显式地指定模板参数,编译器会根据参数自动推导出模板参数的类型。例如:

#include <iostream>

// 通用模板函数
template <typename T>
void print(T value) {
    std::cout << "Value: " << value << std::endl;
}

int main() {
    print(42);          // 隐式实例化为 print<int>(42)
    print(3.14);        // 隐式实例化为 print<double>(3.14)
    print("Hello");     // 隐式实例化为 print<const char*>("Hello")
    return 0;
}

3.2、显示实例化

使用template关键字通过显示声明的方式告诉编译器需要对某个特定类型进行实例化。例如:

#include <iostream>

// 通用模板函数
template <typename T>
void print(T value) {
    std::cout << "Value: " << value << std::endl;
}

// 显式实例化声明
template void print<int>(int);
template void print<double>(double);
template void print<const char*>(const char*);

int main() {
    print(42);          // 使用已实例化的 print<int>(42)
    print(3.14);        // 使用已实例化的 print<double>(3.14)
    print("Hello");     // 使用已实例化的 print<const char*>("Hello")
    return 0;
}

4、模版的特化

有时,对于某些特定类型,可能需要为模板函数提供特定的实现。模版特化的定义应以template<>开头,并且指定具体的类型,例如:

#include <iostream>

// 通用模板定义
template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

// 特化模板,针对 std::string 类型
template <>
std::string max<std::string>(const std::string &a, const std::string &b) {
    return (a.length() > b.length()) ? a : b;
}

int main() {
    int intVal1 = 5, intVal2 = 10;
    std::string str1 = "apple", str2 = "banana";

    std::cout << "Max of int values: " << max(intVal1, intVal2) << std::endl;
    std::cout << "Longer string: " << max(str1, str2) << std::endl;

    return 0;
}

5、注意事项

  • 对于给定的函数名,可以有非模板函数、模板函数与显示具体化模板函数以及它们的重载版本。
  • 具体化优先于常规模板,而非模板函数优于具体化与常规模板。

6、总结

C++ 函数模板是一种强大的工具,它允许程序员编写与类型无关的代码,从而提高代码的可重用性和灵活性。通过模板参数,我们可以定义适用于多种数据类型的函数。此外,模板特化允许我们为特定类型提供特定的实现,从而满足特定需求。掌握函数模板的使用,将极大地提升C++编程的效率和代码质量。

标签:8.2,函数,模版,C++,实例,参数,template,print,模板
From: https://blog.csdn.net/cloud323/article/details/143846554

相关文章

  • 【C++】C++11 新特性揭秘:序章
    C++语法相关知识点可以通过点击以下链接进行学习一起加油!命名空间缺省参数与函数重载C++相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C++内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriority......
  • 宝宝的C++,小学生C++编程启蒙 书籍等
    1、宝宝的C++(2016-11)2、啊哈编程星球:一本书入门Python和C++(2019年09月)啊哈编程星球啊哈编程星球!编程学习从这开始~3、我的第一本算法书(修订版)--2024.24、聪明的算法(2022.07)--6到12岁小读者量身打造的前沿科学大揭秘系列科普书5、走进GoC的编程世界(......
  • C++-------------类和对象
    1.类的定义1.1类定义格式•class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的⽅法或者成员函数。•为了区分成员变量,⼀般习惯上成员变......
  • C++ stl chrono 学习笔记
    chronosinceC++11库的参考手册(英文)|cppreferencechrono库定义了三种(直到c++20)五种(从c++20开始)主要类型以及实用函数和常用类型:cokckstimepointsdurationscalendardates(sinceC++20)timezoneinformation(sinceC++20)clocks时钟由起点(或历元)和滴答率组成......
  • C++-练习-88
    题目:下列程序中每个try后面都使用两个catch块,以确保nbad_index异常导致方法label_val()被调用。请修改该程序,在每个try块后面只使用一个catch块,并使用RTTI来确保合适时调用label_val()。test.h#ifndefQUEUE_H_#defineQUEUE_H_#include<iostream>usingnamespacestd;......
  • C++时间复杂度讲解
    它约等于算法中基本操作重复执行的次数(循环或递归的次数)不是行数!!!最多为O(5)!!!用乘号连接(在嵌套循环中),时间复杂度用O()表示。(O()只是符号)如:for(int=1;i<=n*10/8;i++){      for(intj=1;j<=n*10/2;k++){             for(intk=1;k<n*10;k++)......
  • 双非本 大一的蓝桥杯c++组备赛日记----普通人的极限在哪里?
    本文创作灵感:从开学到现在,刷到许许多多的让人热血沸腾、心生向往的视频,大都是MIT精致生活,清北狂人此类的。刷多之后心中躁动,跃跃欲试,可又知自己能力有限,面对神仙般的人物只能望其项背,每日累得吐血,但成效低微,心中茫然不已。又恰逢手贱误删文件,导致重新装了一遍vs。本人之前看的......
  • C++入门基础知识152—【关于C++ 赋值运算符重载】
    成长路上不孤单......
  • C++入门基础知识151—【关于C++ ++ 和 -- 运算符重载】
    成长路上不孤单......
  • c++小游戏5个
    这里给出5个简单的C++小游戏示例:猜数字游戏:计算机生成一个随机数,玩家需要猜出这个数字是多少。提示玩家猜测的数字是高了还是低了,直到猜中为止。#include<iostream>#include<cstdlib>#include<ctime>intmain(){srand(time(0));intsecretNumber=r......