zoukankan      html  css  js  c++  java
  • 函数模板

    一、简介

    在C++中,数据的类型也可以通过参数来传递,在函数定义时可以不指明具体的数据类型,当发生函数调用时,编译器可以根据传入的实参自动推断数据类型。这就是类型的参数化。

    函数模板是一种特殊的函数,可以使用不同的类型进行调用,对于功能相同的函数,不需要重复编写代码,并且函数模板与普通函数看起来很类似,区别就是类型可以被参数化。

    二、语法

    函数模板的语法:

    template <typename 类型参数1 , typename 类型参数2 , ...> 返回值类型  函数名(形参列表){
      //在函数体中可以使用类型参数
    }
    

    类型参数可以有多个,它们之间以逗号,分隔。类型参数列表以< >包围,形式参数列表以( )包围。

    typename关键字也可以使用class关键字替代,它们没有任何区别。C++ 早期对模板的支持并不严谨,没有引入新的关键字,而是用 class 来指明类型参数,但是 class 关键字本来已经用在类的定义中了,这样做显得不太友好,所以后来 C++ 又引入了一个新的关键字 typename,专门用来定义类型参数。不过至今仍然有很多代码在使用 class 关键字,包括 C++ 标准库、一些开源程序等。

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    using namespace std;
    
    #if 0 
    //int类型数据交换
    void MySwap(int& a, int& b){
    	int temp = a;
    	a = b;
    	b = temp;
    }
    //double类型
    void MySwap(double& a, double& b){
    	double temp = a;
    	a = b;
    	b = temp;
    }
    #endif
    
    //模板技术 类型参数化 编写代码可以忽略类型
    //为了让编译器区分是普通函数  模板函数
    template<class T1,class T2> //template<typename T>告诉编译器 ,下面写模板函数
    void MySwap(T& a, T& b){
    	T temp = a;
    	a = b;
    	b = temp;
    }
    
    void test01(){
    
    	int a = 30;
    	int b = 20;
    	//1 自动类型推导,编译器根据你传的值 进行类型自动推导
    	cout << "a:" << a << " b:" << b << endl;
    	MySwap(a, b); 
    	cout << "a:" << a << " b:" << b << endl;
    
    	double da = 12.3;
    	double db = 21.1;
    	cout << "da:" << da << " db:" << db << endl;
    	MySwap(da, db);
    	cout << "da:" << da << " db:" << db << endl;
    
    	//2. 显式的指定类型
    	MySwap<int>(a, b);
    }
    
    int main(void){	
    	test01();
    	return 0;
    }
    

    三、函数模板跟普通函数

    函数模板跟普通函数一样,也可以被重载

    • C++编译器优先考虑普通函数
    • 如果函数模板可以产生一个更好的匹配,那么就选择函数模板
    • 也可以通过空模板实参列表<>限定编译器只匹配函数模板
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    using namespace std;
    
    template<class T>
    int MyAdd(T a,T b){
    	return a + b;
    }
    
    //普通函数可以进行自动类型转换
    //函数模板必须严格类型匹配
    int MyAdd(int a,int c){
    	return a + c;
    }
    
    void test01(){	
    	int a = 10;
    	int b = 20;
    	char c1 = 'a';
    	char c2 = 'b';
    
    	MyAdd<>(a,b);//限定只使用函数模板
     
    	MyAdd(a,c1);//这个调用,函数模板有更好的匹配,于是调用函数模板
    	MyAdd(a, b);//普通函数int MyAdd(int a,int c)已经能完美匹配,于是调用普通函数
    	MyAdd(c1,b);//这个调用,函数模板有更好的匹配,于是调用函数模板
    }
    
    //函数模板被重载
    template<class T>
    void Print(T a){	
        
    }
    template<class T>
    void Print(T a , T b){
        
    }
    
    int main(void)
    {
    	test01();	
    	return 0;
    }
    

    四、函数模板机制:

    • 编译器并不是把函数模板处理成能够处理任何类型的函数
    • 函数模板通过具体类型产生不同的函数
    • 编译器会对函数模板进行再次编译,在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。
  • 相关阅读:
    转载一篇关于kafka零拷贝(zero-copy)通俗易懂的好文
    kafka的一些核心理论知识
    Kafka知识点(Partitions and Segments)
    kafka: Producer配置和Consumer配置
    kafka: Java实现简单的Producer和Consumer
    SAP抛xml资料到kafka(本机模拟)
    解决方法: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation
    kafka log保存在本机的位置 kafka数据保存的位置
    Kafka: 下载安装和启动
    tomcat错误提示:指定的服务未安装。Unable to open the service 'tomcat9'的原因和解决方法
  • 原文地址:https://www.cnblogs.com/gqw-myblogs/p/14238569.html
Copyright © 2011-2022 走看看