zoukankan      html  css  js  c++  java
  • 函数类型和函数指针类型(摘自 linux c编程一站式学习)

    下面再举几个例子区分函数类型和函数指针类型。首先定义函数类型F:
    typedef int F(void);
    这种类型的函数不带参数,返回值是int 。那么可以这样声明f和g:
    F f, g;

    相当于声明:
    int f(void);
    int g(void);
    下面这个函数声明是错误的:


    F h(void);


    因为函数可以返回void 类型、标量类型、结构体、联合体,但不能返回函数类型,也不能返回数组
    类型。而下面这个函数声明是正确的:


    F *e(void);


    函数e返回一个F *类型的函数指针。如果给e多套几层括号仍然表示同样的意思:


    F *((e))(void);


    但如果把*号也套在括号里就不一样了:


    int (*fp)(void);


    这样声明了一个函数指针,而不是声明一个函数。fp也可以这样声明:


    F *fp;


    通过函数指针调用函数和直接调用函数相比有什么好处呢?我们研究一个例子。回顾第 3 节 “数据
    类型标志”的习题1,由于结构体中多了一个类型字段,需要重新实
    现real_part 、img_part 、magnitude 、angle 这些函数,你当时是怎么实现的?大概是这样吧:

    double real_part(struct complex_struct z)
    {
    if (z.t == RECTANGULAR)
    return z.a;
    else
    return z.a * cos(z.b);
    }


    现在类型字段有两种取值,RECTANGULAR和POLAR ,每个函数都要if ... else ... ,如果类型字段
    有三种取值呢?每个函数都要if ... else if ... else ,或者switch ... case ... 。这样维护代
    码是不够理想的,现在我用函数指针给出一种实现:

    double rect_real_part(struct complex_struct z)
    {
    return z.a;
    }
    double rect_img_part(struct complex_struct z)
    {
    return z.b;
    }
    414
    double rect_magnitude(struct complex_struct z)
    {
    return sqrt(z.a * z.a + z.b * z.b);
    }
    double rect_angle(struct complex_struct z)
    {
    double PI = acos(-1.0);
    if (z.a > 0)
    return atan(z.b / z.a);
    else
    return atan(z.b / z.a) + PI;
    }
    double pol_real_part(struct complex_struct z)
    {
    return z.a * cos(z.b);
    }
    double pol_img_part(struct complex_struct z)
    {
    return z.a * sin(z.b);
    }
    double pol_magnitude(struct complex_struct z)
    {
    return z.a;
    }
    double pol_angle(struct complex_struct z)
    {
    return z.b;
    }
    double (*real_part_tbl[])(struct complex_struct) = { rect_real_part,
    pol_real_part };
    double (*img_part_tbl[])(struct complex_struct) = { rect_img_part,
    pol_img_part };
    double (*magnitude_tbl[])(struct complex_struct) = { rect_magnitude,
    pol_magnitude };
    double (*angle_tbl[])(struct complex_struct) = { rect_angle,
    pol_angle };
    #define real_part(z) real_part_tbl[z.t](z)
    #define img_part(z) img_part_tbl[z.t](z)
    #define magnitude(z) magnitude_tbl[z.t](z)
    #define angle(z) angle_tbl[z.t](z)


    当调用real_part(z)时,用类型字段z.t 做索引,从指针数组real_part_tbl 中取出相应的函数指针
    来调用,也可以达到if ... else ... 的效果,但相比之下这种实现更好,每个函数都只做一件事
    情,而不必用if ... else ... 兼顾好几件事情,比如rect_real_part 和pol_real_part 各做各的,
    互相独立,而不必把它们的代码都耦合到一个函数中。

    “低耦合,高内聚”(Low Coupling, HighCohesion)是程序设计的一条基本原则,这样可以更好地复用现有代码,使代码更容易维护。如果类型字段z.t 又多了一种取值,只需要添加一组新的函数,修改函数指针数组,原有的函数仍然可以不加改动地复用。

  • 相关阅读:
    android WebView 加载html5
    android 摄像头的使用
    android 传感器类 sensor
    关于java的一些东西
    android 网络连接管理机制
    利用Layout实现Button的不规则布局
    Android 推送通知指南(转载)
    android开发小问题随记(附1)
    ubuntu下搭建android开发环境(转载)
    北斗小辣椒双核升级攻略之一
  • 原文地址:https://www.cnblogs.com/bigbigtree/p/2979334.html
Copyright © 2011-2022 走看看