zoukankan      html  css  js  c++  java
  • 函数指针详解

    简化理解:

    1、typedef int (*F)(int);是定义指针,指向一个返回值函数。可以定义一个变量:F f,那f是一个指向一个函数的指针,调用f就是调用这个函数。如下表示:

    定义一个方法:
    int f(int a);
    给它一个指针;
    int (*h)(int);
    h=f;或者h=&f;

    int (*h)(int)=f;

     

    (1)函数的定义:Functions ara named units of computation.


         这个定义从本质上确定了函数是什么东西,准确来说它只是一段执行序列,一段代码,是一段被赋予名称的代码。

    代码不具备有效空间资源(在特定代码区中),代码中的变量指向的对象会在特别的区域占有空间,但是就代码本身而言是没有空间占有的概念。从汇编的角度(指令的角度),代码被划成一条条指令,而指令中的地址有可能指向一个数据空间。所以程序在执行的时候空间大概有指令空间和数据空间两种。

    函数是基于对代码的重用而提出的概念,代码被使用的时候并不会自动复制,而是公用一个代码(指令序列),(这里不考虑inline方式)。不同的执行过程的区别就在于函数代码中变量,每一次函数的调用,并不会为函数代码分配空间,而会从新为它需要的变量分配空间。这样就可以达到代码重用而各有其用的效果。

    所以,虽说代码(指令序列)和变量都有空间概念,但是他们是不同的,代码是一种通用的东西,变量是代表一种特定场合的东西。有空间必有指针,所以函数是有指针的。

     

    (1)函数指针

     

    定义一个变量的:
    int a=0;
    给变量一个指针;
    int *b=&a;

    这个指针拥有两个信息,一就是变量类型(这个决定了它的空间大小和上面的操作),另一个就是地址。

    定义一个方法:
    int f(int a);
    给它一个指针;
    int (*h)(int);
    h=f;或者h=&f;

    int (*h)(int)=f;

    那么这个函数指针需要的信息有哪些?地址肯定是有的,大小和在上面的操作就不好和变量学习了,因为它并不是被操作的对象,并且代码占空间大小也没有什么实际意义。那么方法的指针到底需要包含哪些东西呢?

    我们知道一个方法对外需要表现怎么才能被正确的使用相关信息,就像一个变量,需要对外表现它的类型一样。所以方法需要表现该方法的返回类型,以及参数列表,这也就是方法的原型(prototype);当然不能忘掉方法的地址。

    我们发现定义变量的指针与定义函数的指针的唯一区别就是需要多加函数列表的定义。这样就是形成了一个函数prototype。

    函数名与函数地址是通用的。也就是说f既是函数名,&f表示函数指针,f本身也可以表示为函数指针。从这个角度上讲,函数没有实体的概念,只有指针的概念。

     

    如上面所示:似乎定义一个方法的指针不那么方便,因为要给定除方法返回值和参数列表,在加上一些const属性,有时候并不那么容易。从原理上讲,方法的指针是有一个“类型”的,更准确地说应该是prototype,那么如果我们能够将这个"复杂“的prototype转换成一个type,那么定义方法的指针就方便了,而且统一。

    typedef int (*F)(int);
    上面一句话什么意思呢?就是定义F,为一个方法指针的prototype,以后要定义这样的方法指针就可以:
    F f;
    对很简单,像定义变量一样。

    还记得以前使用typedef来定义一个变量类型吗?“你先做一个示范,然后以后的所有类型就按照你来做)。这里也是一样的,定义方法指针的prototype和定义方法指针很相像。


    通常来讲,方法和变量很像,都有自己的prototype。变量的prototype很简单,只有type而已,而方法的prototype比较复杂还有参数列表。

    所以我们讲一个变量的类型是这样的:
    int;
    一个变量指针的类型是这样的:
    int *;
    那么一个方法的prototype是这样的:
    int (*)(int);

    不要不习惯。其实方法也有类型,而不只是方法指针类型,但是前面提到方法的对象(方法名),与方法指针基本是通用的。多者说,你也可以认为方法也是一个特殊类型,只是在使用的时候既可以表示该方法对象,也可以表示方法的指针。

     

    方法作为方法参数和返回值。
    int fun1(int);
    int fun(int, int (*)(int));

    int main()
    {
      cout<<fun(10,fun1);
    }
    int fun(int a,int (*b)(int ))
    {
      return  b(a); 
    }


    int fun1 (int a)
    {
     return a;
    }

    赋值方法参数的时候,使用方法名就可以了,它会自动转换为指针(因为方法名誉方法指针是通用的),但是这种模式在返回值的时候就不是这样的了。

    typedef int (*F)(int);
    F fun()
    {

    int fun1 (int a);
    return fun1;

    }
    int fun1(int a)
    {
     return a;
    }

    int main()
    {
       int (*a)(int)=fun();
       cout<<a(10);
    }

     

    对于定义一个方法函数指针的方法,最好使用typedef来定义一个方法的类型,然后就比较好看些。如果直接写;

    使用typedef:
    typedef int (*F)(int);
    F fun()
    {

    int fun1 (int a);
    return fun1;

    }
    直接写:
    int (*fun())(int);有时候会比较迷惑,方法指针的类型是:int (*)(int);照理讲应该是这样的:
    int (*)(int) fun();但是这样的表达,编译器会不知道怎么认识,我们从方法和变量之间的同性来考虑。
    方法被使用时以其返回变量为基准的,也就是说,如果你这个方法fun返回一个变量指针,那么就是int * fun();如果是方法指针,则是int (*fun())(int);

     

    方法对象。


    事实上,方法是可以申请对象的,也就是说不一定是方法的指针。


    int fun(int);//这是一个申明。申明fun是一个返回int,并且具有参数int的方法,注意不是方法的指针。

    但是int fun(int)=fun1;确实编译错误。说fun不能被赋值。

    的确有这样的类型:
    typedef int F(int);
    但是这个类型基本不能直接使用。

    int fun1(int a)
    {
      return a;
    }
    我们不能定义一个函数返回一个方法。
    F fun()
    {
      return  fun1;

    }
    只能这样:
    F *fun()
    {
     return fun1;
    }
    可知还是返回指向某个方法的指针。因为方法的对象与前面int fun(int)不能被赋值冲突。所以C++中只能将方法的指针传来传去。

    要知道参数是可以这么做的。
    int fun(F f);
    这个方法就是一个具有f参数的方法,返回int类型的返回值。
    但是实际上,这里是系统自动将这个方法对象转换成方法指针。要知道方法对象和指针是通用的!

    所以区别就是,作为参数的方法对象可以自动转换成方法指针。所以返回值的方法对象不能自动转化,所以要显示的表明是指针。

  • 相关阅读:
    .NET微服务调查结果
    发布基于Orchard Core的友浩达科技官网
    Followme Devops实践之路
    积极参与开源项目,促进.NET Core生态社区发展
    Service Fabric 与 Ocelot 集成
    “.Net 社区大会”(dotnetConf) 2018 Day 1 主题演讲
    Project file is incomplete. Expected imports are missing 错误解决方案
    稳定工作和创业之间的抉择
    回顾4180天在腾讯使用C#的历程,开启新的征途
    ML-Framework:ML.NET 0.3 带来新组件
  • 原文地址:https://www.cnblogs.com/nktblog/p/2918090.html
Copyright © 2011-2022 走看看