zoukankan      html  css  js  c++  java
  • 【转】王老师 C++ 函数重载和模板

    (1)连接指示符:通知编译器,某个函数是由其它语言编写的。

    语法:

    1. extern "语言名" 函数原型;

    2. extern "语言名"

    {

      函数原型1;

      ...

      函数原型n;

    }

    3.extern "语言名"

    {

      include 文件名

    }

    原因:C++语言编译器会对函数重载进行重命名(Name-Mangling);但是在C语言中,由于不允许出现同名的全局函数(静态全局函数除外),不需进行重命名。所以在程序中如果出现了extern "C" fun(int);就不应出现extern "C" fun(double);

    例如:

    extern "C" fun(int);
    extern "C" fun(double);
    int main(void)
    {
     fun(3);
     fun(3.5);
     return 0;
    }

    error C2733: second C linkage of overloaded function 'fun' not allowed

    (2)函数重载的解析

    根据函数调用中的实参,确定要执行的函数。

    结果:

    1.没有函数可调用(出错);

    2.恰有一个可调用;

    3.有多个可调用,二义性(在编译时发现)。

    解析的时机:

    1.函数调用时解析;

    例如:

    void fun(long);

    void fun(int);

    求:fun(3);

    2.取函数地址。

    例如:

    void g(void (*fp)(long));

    void g(void (*fp)(int));

    求:g(f);

    (3)实参类型转换

    1.精确匹配。包含4种情形(其中a,b.c称为左值转换):

    a.从左值到右值的转换

    b.从数组到指针的转换

    c.从函数到指针的转换

    例如: int fun(int);

    void g(int (*fp)(int));

    求:g(fun);

    d.限定修饰符转换

    例如:int *q;

    void fun(const int * p);

    求:fun(q);

    2.提升

    a.带符号或不带符号的char,short类型转换为int型。

    b.float  => double

    c.bool  => int

    3.标准转换

    a.算术类型间的转换,这与提升a,b是一样的。

    b.整型0到各种指针;各种指针 => void *

    c.各种算术指针 => bool

    4.用户自定义转换

    标准转换序列:

    0个或1个左值转换 -> 0个或1个提升或标准转换 -> 0个或1个限定修饰符转换

    重载函数解析的过程:

    1.确定候选函数集

    a.调用点可见的同名函数

    b.实参类型定义所属名字空间中的同名函数

    2.确定可行函数集

    a.实参个数 <= 形参个数,形参多出的必有缺省值。

    b.有实参到形参的转换序列。

    3.确定最佳可行函数。

    (4)函数模板

    1.功能不同或者是功能太大时不要使用函数重载。

    所谓函数重载,是指自动生成各种类型函数的算法。

    定义语法:template <模板参数表>

                       值类型 函数名 (形参表)

                       函数体

    模板参数,由两类参数构成:

    a.模板类型参数

    声明方式: typename 标识符

    表示一个特定类型。

    b.模板非类型参数

    声明方式: 通常的变量声明

    表示一个值。

    说明:

    值类型,可以是内置类型,用户定义类型,模板类型参数

    形参表,允许类型如上

    函数表,定义的局部变量类型如上。

    例如:

    #include <iostream>
    using namespace std;

    template <typename T, int size>
    T min(T (&a)[size])
    {
     int i;
     T x = a[0];
     for(i = 0; i < size; i++)
     {
      if (x > a[i])
       x = a[i];
     }
     return x;
    }

    template <typename T>
    T min(T *a, int size)
    {
     int i;
     T x = a[0];
     for(i = 0; i < size; i++)
     {
      if (x > a[i])
       x = a[i];
     }
     return x;
    }

    int main()
    {
     int a[] = {1, 2, 3, -1, 5, 2, 4};
     cout << min(a) << endl;
     cout << min(a, 7) << endl;
    }

    模板实例化:

    根据函数调用,自动生成函数。

    说明:

    显示指定模板参数语法:

    函数名<实参名, ..., 实参名>(实参表);

    例如:

    template <typename T1, typename T2, typename T3>

    T1  fun(T2 x, T3 y)

    {

      ...

    }

    fun<int, int, double>(3, 2.5);

    函数实参推演:从函数调用的实参确定模板参数的过程。

    模板特化语法:

    template <>

    值类型 函数名<实际模板参数值>(形参表)

    函数体

    举例略。

    函数模板的重载:

    1.求候选函数集,较为复杂,略。

    2.求可行函数集

    3.最佳可行函数集

     在写函数模板时,可以先写好特殊类型下的,再写一般的。例如:排序函数模板程序如下。

    #include <iostream>
    using namespace std;

    template <typename T>
    void sort(T *array, int n)
    {
     cout << "sort in template 1..." << endl;

     //下标
     int i, j;

     //暂存待排序元素
     T tmp;

     for(i = 1; i < n; i++)
     {
      tmp = array[i];
      j = i - 1;
      //寻找插入位置
      while(j >= 0 && array[j] > tmp)
      {
       array[j + 1] = array[j];
       j--;
      }
      array[j + 1] = tmp;
     }
    }

    template <typename T1, typename T2>
    void sort(T1 *array, int n, T2 fun)
    {
     cout << "sort in template 2..." << endl;

     //下标
     int i, j;

     //暂存待排序元素
     T1 tmp;

     for(i = 1; i < n; i++)
     {
      tmp = array[i];
      j = i - 1;
      //寻找插入位置
      while(j >= 0 && fun(array[j], tmp))
      {
       array[j + 1] = array[j];
       j--;
      }
      array[j + 1] = tmp;
     }
    }

    int cmp(int a, int b)
    {
     return a > b;
    }

    int main()
    {
     int a[] = {1, 3, 5, 8, 9, 4, 6, 7, 2};
     int size = sizeof(a) / sizeof(int);
     sort(a, size);
     for(int i = 0; i < size; i ++)
     {
      cout << a[i] << endl;
     }
     cout << endl;

     sort(a, size, cmp);
     for(int i = 0; i < size; i ++)
     {
      cout << a[i] << endl;
     }
     cout << endl;

     double b[] = {1.0, 3.0, 5.0, 8.0, 9.0, 4.0, 6.0, 7.0, 2.0};
     int dsize = sizeof(b) / sizeof(double);
     sort(b, dsize);
     for(int j = 0; j < dsize; j++)
     {
      cout << b[j] << endl;
     }
     cout << endl;

     sort(b, dsize, cmp);
     for(int j = 0; j < dsize; j++)
     {
      cout << b[j] << endl;
     }

    }

    【来  源】:http://blog.csdn.net/nomad2/archive/2006/06/10/787013.aspx

  • 相关阅读:
    卸载cuda,以及N卡驱动
    ubuntu 16.04 从gcc 5.4 安装gcc 5.3.0
    Check failed: status == CUBLAS_STATUS_SUCCESS (13 vs. 0) CUBLAS_STATUS_EXECUTION_FAILED
    ubuntu16.04 caffe cuda9.1 segnet nvidia gpu安装注意的点
    ubuntu16.04安装docker
    进程管理
    Dev TextEdit 只输入数字
    dev gridcontrol添加右键菜单
    WinForm rdlc 报表自定义datatable数据源
    DevExpress GridControl使用方法总结2 属性说明
  • 原文地址:https://www.cnblogs.com/cappuccino/p/1757402.html
Copyright © 2011-2022 走看看