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

    模板以template关键字和一个形参表开头

    参数至少是有一个模板类型

     1 #include <iostream>
     2 using namespace std;
     3 
     4 //T通用数据类型
     5 template <typename T>
     6 T MAX(T *p, const int n)
     7 {
     8     T maxdata(p[0]);
     9 
    10     for (int i = 0; i < n; i++)
    11     {
    12         if (maxdata < p[i])
    13         {
    14             maxdata = p[i];
    15         }
    16     }
    17 
    18     return maxdata;
    19 }
    20 
    21 void main()
    22 {
    23     int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
    24     double b[10] = { 1,2,3,4,5,6,7,8,9,10 };
    25 
    26     std::cout << MAX(a, 10) << std::endl;
    27     std::cout << MAX(b, 10) << std::endl;
    28 
    29     system("pause");
    30 }

    函数参数不允许使用自动变量

    //error C3533: 参数不能为包含“auto”的类型

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int putnum(auto num)//error C3533: 参数不能为包含“auto”的类型
     5 {
     6 
     7 }
     8 
     9 void main()
    10 {
    11 
    12     system("pause");
    13 }

    函数模板中可以使用inline

     1 #include <iostream>
     2 using namespace std;
     3 
     4 template <class T>
     5 inline T getX3(T x)
     6 {
     7     return x*x*x;
     8 }
     9 
    10 void main()
    11 {
    12     std::cout << getX3(1 + 2) << std::endl;//27
    13 
    14     system("pause");
    15 }

    函数模板根据类型覆盖

    //模板为空,明确类型
    template <>
    void swap1(info &info1, info &info2)
    {
    std::cout << "特有函数模板" << std::endl;
    info temp = info1;
    info1 = info2;
    info2 = temp;
    }

    不写上T

     1 #include <iostream>
     2 using namespace std;
     3 
     4 //函数模板实现通用,可以根据自有数据类型,进行优化
     5 //结构体可以直接赋值
     6 //所有成员都是公有的类型可以赋值
     7 
     8 struct info
     9 {
    10     char name[100];
    11     double db;
    12     int data;
    13 };
    14 
    15 template <typename T>
    16 void swap1(T &a, T &b)
    17 {
    18     std::cout << "通用函数模板" << std::endl;
    19     T temp = a;
    20     a = b;
    21     b = temp;
    22 }
    23 
    24 //模板为空,明确类型
    25 template <>
    26 void swap1(info &info1, info &info2)
    27 {
    28     std::cout << "特有函数模板" << std::endl;
    29     info temp = info1;
    30     info1 = info2;
    31     info2 = temp;
    32 }
    33 
    34 void main()
    35 {
    36     info info1 = { "hello",20.9,10 };
    37     info info2 = { "world",9.2,1 };
    38 
    39     swap1(info1, info2);//交换两个结构体
    40 
    41     std::cout << info1.name << " " << info1.db << " " << info1.data << std::endl;
    42     std::cout << info2.name << " " << info2.db << " " << info2.data << std::endl;
    43 
    44     system("pause");
    45 }

    //如果类有私有成员变量,不可以用大括号初始化

    //类的对象之间默认是可以直接赋值

    //类、结构体都有一个默认赋值操作=浅拷贝

    //深拷贝用得最多,函数模板的覆盖

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include <iostream>
     3 using namespace std;
     4 
     5 //如果类有私有成员变量,不可以用大括号初始化
     6 //类的对象之间默认是可以直接赋值
     7 //类、结构体都有一个默认赋值操作=浅拷贝
     8 //深拷贝用得最多,函数模板的覆盖
     9 
    10 class info
    11 {
    12 private:
    13     int num;
    14 public:
    15     char name[100];
    16     char *p;
    17     int data;    
    18     void set(int X)
    19     {
    20         this->num = X;
    21     }
    22     int get()
    23     {
    24         return this->num;
    25     }
    26 };
    27 
    28 template <typename T>
    29 void swap1(T &a, T &b)
    30 {
    31     std::cout << "通用函数模板" << std::endl;
    32     T temp = a;
    33     a = b;
    34     b = temp;
    35 }
    36 
    37 //模板为空,明确类型
    38 template <>
    39 void swap1(info &info1, info &info2)
    40 {
    41     std::cout << "特有函数模板" << std::endl;
    42     info temp = info1;
    43     info1 = info2;
    44     info2 = temp;
    45 }
    46 
    47 //函数,对一个对象进行深拷贝,需要自己函数模板重载
    48 
    49 void main()
    50 {
    51     info info1;
    52     info info2;
    53 
    54     std::strcpy(info1.name, "hello");
    55     std::strcpy(info2.name, "world");
    56     info1.p = new char[10];
    57     std::strcpy(info1.name, "info1.p");
    58     info2.p = new char[10];
    59     std::strcpy(info2.name, "info2.p");
    60     info1.data = 102;
    61     info2.data = 201;
    62     info1.set(89);
    63     info2.set(98);
    64 
    65     swap1(info1, info2);
    66 
    67     std::cout << info1.name << " " << info1.p << info1.data << " " << info1.get() << " " << std::endl;
    68     std::cout << info2.name << " " << info1.p << info2.data << " " << info2.get() << " " << std::endl;
    69 
    70     system("pause");
    71 }

    //函数模板可以对类型进行优化重载,根据类型会覆盖

    //如果仍然要使用模板函数,需要实例化

    显式比较准则

    函数模板名<模板参数>(参数列表)

    add<int>(a, b);//T add,实例化

    add<int>(db1, db2);//T add,实例化

    add<double>(db1, db2);//T add,实例化

     1 #include <iostream>
     2 using namespace std;
     3 
     4 //函数模板可以对类型进行优化重载,根据类型会覆盖
     5 //如果仍然要使用模板函数,需要实例化
     6 
     7 template <class T>//函数模板
     8 T add(T a, T b)
     9 {
    10     std::cout << "T add" << std::endl;
    11     return a + b;
    12 }
    13 
    14 int add(int a, int b)//一般函数
    15 {
    16     std::cout << "int add" << std::endl;
    17     return a + b;
    18 }
    19 
    20 void main()
    21 {
    22     int a(10), b(20);
    23 
    24     double db1(10.9), db2(10.8);
    25 
    26     add(a, b);//int add
    27 
    28     add(db1, db2);//T add
    29 
    30     add<int>(a, b);//T add,实例化
    31 
    32     add<int>(db1, db2);//T add,实例化
    33 
    34     add<double>(db1, db2);//T add,实例化
    35 
    36     system("pause");
    37 }

    函数可变参数通用类型,函数模板

    //通用可变参数模板

    //可处理不限定个数的参数,处理不同类型

    //根据不同的需求,采用不同的设计

    //设计可以修改原来的数据的,不要加上const,要引用,void showall(const &value, Args &...args)

    //设计可以修改副本,不要const,不要引用,void showall(T value, Args...args)

    //设计不可以修改原来的数据,且不能修改副本void showall(const T value, const Args...args)

    //设计引用原来的数据,但不可以修改void showall(const T &value, const Args &...args)

     1 #include <iostream>
     2 using namespace std;
     3 
     4 //通用可变参数模板
     5 //可处理不限定个数的参数,处理不同类型
     6 
     7 void showall()//空函数,必须保留,作用:接口作用,最后结束递归
     8 {
     9 
    10 }
    11 
    12 //根据不同的需求,采用不同的设计
    13 //设计可以修改原来的数据的,不要加上const,要引用,void showall(const &value, Args &...args)
    14 //设计可以修改副本,不要const,不要引用,void showall(T value, Args...args)
    15 //设计不可以修改原来的数据,且不能修改副本void showall(const T value, const Args...args)
    16 //设计引用原来的数据,但不可以修改void showall(const T &value, const Args &...args)
    17 
    18 template <typename T, typename...Args>
    19 void showall(const T &value, const Args &...args)
    20 {
    21     std::cout << value << std::endl;
    22     showall(args...);//继续传递,递归
    23     std::cout << std::endl;
    24 }
    25 
    26 void main()
    27 {
    28     int num1(10), num2(9), num3(11);
    29 
    30     double db1(10.8), db2(10.9);
    31 
    32     char str[40] = "hello";
    33 
    34     char ch = 'A';
    35     
    36     showall(num1);
    37 
    38     showall(num1, num2, num3);
    39 
    40     showall(db1, db2, num1, ch);
    41 
    42     showall(db1, db2, num1, ch, str);
    43 
    44     system("pause");
    45 }

    函数模板重载,array数组作为参数

     1 #include <iostream>
     2 #include <array>
     3 using namespace std;
     4 
     5 template <typename T>
     6 void showarray(std::array<T, 10> myarray, int n)//对象数组
     7 {
     8     std::cout << "对象数组" << std::endl;
     9     for (int i = 0; i < n; i++)
    10     {
    11         std::cout << myarray[i] << " ";
    12     }
    13     std::cout << std::endl;
    14 }
    15 
    16 template <typename T>
    17 void showarray(std::array<T *, 10> myarray, int n)//指针数组
    18 {
    19     std::cout << "指针数组" << std::endl;
    20     for (int i = 0; i < n; i++)
    21     {
    22         std::cout << *myarray[i] << " ";
    23     }
    24     std::cout << std::endl;
    25 }
    26 
    27 void main()
    28 {
    29     std::array<int, 10>intarray = { 1,2,3,4,5,6,7,8,9,10 };//创建一个数组,数组的元素类型是int
    30 
    31     std::array<int *, 10>pintarray;//创建一个数组,数组的元素类型是int *
    32 
    33     std::array<int **, 10>ppintarray;//创建一个数组,数组的元素类型是int **
    34 
    35     for (int i = 0; i < 10; i++)
    36     {
    37         pintarray[i] = &intarray[i];//赋值
    38     }
    39 
    40     for (int i = 0; i < 10; i++)
    41     {
    42         ppintarray[i] = &pintarray[i];//赋值
    43     }
    44 
    45     showarray(intarray, 10);//对象数组
    46 
    47     showarray(pintarray, 10);//指针数组
    48 
    49     showarray(ppintarray, 10);//指针数组
    50 
    51     system("pause");
    52 }

    面试:

    typename与class区别

    关键字typename作为类型前的标识符号

    1 template <class T>
    2 class MyClass
    3 {
    4     typename T::SubType * ptr;
    5     //typename指出SubType是T中定义的一个类型,因此ptr是一个指向T::SubType的指针
    6     //如果不加上typename,表达式被认为是T中的静态成员SubType和ptr的乘积
    7 };

    C++的一般规则是,除了以typename修饰以外,template内的任何标识符号都被视为一个值value,而非一个类型type

    typename的第二个作用:在模板声明中替换关键字class

    template <typename T>
    class MyClass;

    软件工程规范,用typename,不用class

  • 相关阅读:
    ASP获取上月本月下月的第一天和最后一天
    JS表单提交
    JS分段传输数据
    SQLServer存储过程实现单条件分页
    ASP从HTML标签中提取中文
    ViewData、ViewBag和 TempData
    Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
    Java实现DFS深度优先查找
    Java实现BFS广度优先查找
    Java实现二分查找(折半查找)
  • 原文地址:https://www.cnblogs.com/denggelin/p/5648632.html
Copyright © 2011-2022 走看看