C++初阶模板--1

简介: C++初阶模板--1

介绍:


       我们先认识以下C++中的模板。模板是一种编程技术,允许程序员编写与数据类型无关的代码,它是一种泛型编程的方式,可以用于创建可处理多种数据类型的函数或类,也就是说泛型编程就是编写与类型无关的通用代码,是代码复用的一种手段,而模板是泛型编程的基础。其中,模板分为函数模板和类模板。


函数模板:


       函数模板是一种通用的函数定义,可以接受多种类型作为输入,并生成对应的特定类型函数。


格式:


       template


       template 返回值类型 函数名(参数列表){}


//定义一个可以实现多种类型交换的函数
template<typename T>
void Swap(T& left, T& right)
{
    T temp = left;
    left = right;
    right = temp;
}

       注意:上面的typename是用来定义模板参数的关键字,这可使用class,我们目前可先认为class与typename无任何区别,但是这里不能使用struct来代替。


函数模板的工作原理:


       这里要说明的是函数模板是一个 “ 蓝图 ”,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。


       在编译器编译阶段,当调用函数模板时,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,其它类型也是如此。


660427aa106f462d9ce68e7bedda0aab.png


       注意:函数模板并不会为每个可能的类型组合生成函数,后文会对齐深入讲解。


函数模板的实例化:


       函数模板根据传入的实参类型生成特定类型的函数,然后调用这些函数,此过程称为函数模板的实例化。其中,模板参数实例化分为:隐式实例化和显式实例化。


       隐式实例化:让编译器根据实参推演模板参数的实际类型。

template<class T>
T Add(const T& left, const T& right)
{
    return left + right;
}
int main()
{
    //隐式实例化
    Add(1, 2);
    Add(1.2, 1.3);
    return 0;
}


       显式实例化:在函数名后的<>中指定模板参数的实际类型。

template<class T>
T Add(const T& left, const T& right)
{
    return left + right;
}
int main()
{
    int a = 10;
    double b = 20.0;
    //显式实例化
    Add<int>(a, b);
    return 0;
}


       注意:当进行类型转换时,如果编译器没有找到与实参类型匹配的函数模板,它会自动进行隐式实例化,如果还无法确定实例化的类型,就会报错。    


       下面我们观察以下代码的问题:


template<class T>
T Add(const T& left, const T& right)
{
    return left + right;
}
template<typename T1, typename T2>
T1 add(const T1& left, const T2& right)
{
    return left + right;
}
int main()
{
    Add(1, 1.2);//系统报错
    Add(1, (int)1.2);//强制转换,运行正常
    Add<int>(1, 1.2);//显示实例化,运行正常
    add(1, 1.2);//参数匹配,运行正常
    return 0;
}

       以上语句不能通过编译是因为在编译期间,当编译器看到该实例化时,需要推演其实参类型

通过实参1将T推演为int,通过实参1.2将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int 或者 double类型,进而报错。


       注意:在模板中,编译器一般不会进行类型转换操作。


       解决以上方法有三种:1. 直接强制转化    2. 使用显式实例化     3. 设置多个模板参数


模板函数与非模板函数:


       一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数,当调用时,如果其他条件都相同,会优先调用非模板函数。如果模板可以产生一个具有更好匹配的函数,那么将选择模板函数。


int Add(int left, int right)
{
    return left + right;
}
template<class T>
T Add(T left, T right)
{
    return left + right;
}
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
    return left + right;
}
int main()
{
    Add(1, 2); //调用非模板函数
    Add<int>(1, 2); //显示实例化,调用模板函数
    Add(1, 2); //与非函数模板类型完全匹配,调用非函数模板
    Add(1, 2.0); //模板函数可以生成更加匹配的版本,调用函数模板
    return 0;
}

       这里再强调一次,模板函数不允许自动类型转换,但普通函数可以进行自动类型转换。

C++初阶模板--2https://developer.aliyun.com/article/1424653?spm=a2c6h.13148508.setting.18.214f4f0eYmzRjY

相关文章
|
2月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
112 10
|
23天前
|
安全 编译器 C++
【C++11】可变模板参数详解
本文详细介绍了C++11引入的可变模板参数,这是一种允许模板接受任意数量和类型参数的强大工具。文章从基本概念入手,讲解了可变模板参数的语法、参数包的展开方法,以及如何结合递归调用、折叠表达式等技术实现高效编程。通过具体示例,如打印任意数量参数、类型安全的`printf`替代方案等,展示了其在实际开发中的应用。最后,文章讨论了性能优化策略和常见问题,帮助读者更好地理解和使用这一高级C++特性。
38 4
|
23天前
|
算法 编译器 C++
【C++】模板详细讲解(含反向迭代器)
C++模板是泛型编程的核心,允许编写与类型无关的代码,提高代码复用性和灵活性。模板分为函数模板和类模板,支持隐式和显式实例化,以及特化(全特化和偏特化)。C++标准库广泛使用模板,如容器、迭代器、算法和函数对象等,以支持高效、灵活的编程。反向迭代器通过对正向迭代器的封装,实现了逆序遍历的功能。
33 3
|
26天前
|
编译器 C++
【c++】模板详解(1)
本文介绍了C++中的模板概念,包括函数模板和类模板,强调了模板作为泛型编程基础的重要性。函数模板允许创建类型无关的函数,类模板则能根据不同的类型生成不同的类。文章通过具体示例详细解释了模板的定义、实例化及匹配原则,帮助读者理解模板机制,为学习STL打下基础。
29 0
|
2月前
|
编译器 程序员 C++
【C++打怪之路Lv7】-- 模板初阶
【C++打怪之路Lv7】-- 模板初阶
18 1
|
2月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
54 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
2月前
|
算法 编译器 C++
【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧
【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧
84 2
|
2月前
|
存储 编译器 C++
【C++篇】引领C++模板初体验:泛型编程的力量与妙用
【C++篇】引领C++模板初体验:泛型编程的力量与妙用
43 2
|
2月前
|
存储 算法 编译器
【C++】初识C++模板与STL
【C++】初识C++模板与STL
|
2月前
|
编译器 C++
【C++】模板进阶:深入解析模板特化
【C++】模板进阶:深入解析模板特化