zoukankan      html  css  js  c++  java
  • 恼人的函数指针(二)

    原文链接:http://www.cnblogs.com/AnnieKim/archive/2011/12/04/2275589.html

    前面曾写过一篇恼人的函数指针(一)。总结了普通函数指针的声明、定义以及调用。还有函数指针数组。函数指针用作返回值等。可是作为C++的

    研读。我发现我漏掉了一个最重要的内容。就是指向类成员的指针。这里将做对应补充(相关代码測试环境为vs 2010)。

    指向类成员的指针总的来讲能够分为两大类四小类(指向数据成员还是成员函数。指向普通成员还是静态成员)。以下一一做介绍:

    一、指向类的普通成员的指针(非静态

    1、指向类成员函数的指针

    简单的讲,指向类成员函数的指针与普通函数指针的差别在于。前者不仅要匹配函数的參数类型和个数以及返

    回值类型,还要匹配该函数指针所属的类类型。总结一下,比較下面几点:

    a)參数类型和个数

    b)返回值类型

    c)所属的类类型(特别之处)

    究其原因。是由于非静态的成员函数必须被绑定到一个类的对象或者指针上,才干得到被调用对象的this指针。

    然后才干调用指针所指的成员函数(我们知道。全部类的对象都有自己数据成员的拷贝,可是成员函数都是共

    用的。为了区分是谁调用了成员函数,就必须有this指针,this指针是隐式的加入到函数參数列表里去的)。

    明确了这点,接下来就简单了。

    声明:与普通函数作为区分。指向类的成员函数的指针仅仅须要在指针前加上类类型就可以,格式为:

    typedef 返回值 (类名::*指针类型名)(參数列表);

    赋值:仅仅须要用类的成员函数地址赋值就可以,格式为:

    指针类型名  指针名 = &类名::成员函数名;

    注意:这里的这个&符号是比較重要的:不加&。编译器会觉得是在这里调用成员函数,所以须要给出參数列

    表,否则会报错。加了&,才觉得是要获取函数指针。这是C++专门做了差别对待。

    调用:调用方法也非常easy,针对调用的对象是对象还是指针,分别用.*和->*进行调用,格式为:

    (类对象.*指针名)(參数列表);

    (类指针->*指针名)(參数列表);

    (既然是指针, 无论是数据类型的指针。 还是函数指针, 无论是普通函数指针还是类函数成员指针。 都应该依照

    习惯加一个&去取地址符, 只是对于普通函数, 编译器做了特殊的处理, 只是我本人觉得会让人误解, 全部东

    西, 涉及到类的, 基本上都会有个类域; 当应引用指针的值的时候, 我们应该和普通的指针一样。 用*去引用

    符。

    提醒一下大家。 由于类的.和->运算符的优先级都高于去引用符*, 所以上面的能那么写, 不清楚的读者可

    做自己看看运算符的优先级.)

    注意:这里的前面一对括号是非常重要的。由于()的优先级高于成员操作符指针的优先级。

    以下举个简单的样例就一目了然了:

    复制代码
    class A;
    typedef void (A::*NONSTATICFUNCPTR)(int);    //typedef
     
    class A
    {
    public:
        void NonStaticFunc(int arg)
        {
            nonStaticMember = arg;
            cout << nonStaticMember << endl;
        }
    private:
        int    nonStaticMember;
    };
     
    int main()
    {
        NONSTATICFUNCPTR funcPtr = &A::NonStaticFunc;
     
        A a;
        (a.*funcPtr)(10);        //通过对象调用
     
        A *aPtr = new A;
        (aPtr->*funcPtr)(10);    //通过指针调用
     
        return 0;
    }
    复制代码

    2、指向类数据成员的指针

    成员函数搞懂了,数据成员也就easy了。仅仅要推断下面两点是否一致就可以:

    a)数据成员类型

    b)所属的类类型

    另外,声明、赋值还有调用方法等这些是和前面类似的,再举个样例吧:

    复制代码
    class A;
    typedef int(A::*NONSTATICDATAPTR);        //typedef
     
    class A
    {
    public:
        A(int arg) :nonStaticMember(arg){}
        int    nonStaticMember;
    };
     
    int main()
    {
        NONSTATICDATAPTR dataPtr = &A::nonStaticMember;
     
        A a(10);
        cout << a.*dataPtr;        //通过对象引用
     
        A *aPtr = new A(100);
        cout << aPtr->*dataPtr;    //通过指针引用
     
        return 0;
    }
    复制代码

    执行结果。当然是各自输出10和100啦。

    二、指向类的静态成员的指针

    类的静态成员和普通成员的差别在于,他们是不依赖于详细对象的。全部实例化的对象都共享同一个静态成员,

    所以静态成员也没有this指针的概念。所以,指向类的静态成员的指针就是普通的指针

    看以下的样例就明确了:

    复制代码
    typedef const int *STATICDATAPTR;
    typedef int(*STATICFUNCPTR)();        //跟普通函数指针是一样的
     
    class A
    {
    public:
        static int StaticFunc() { return staticMember; };
        static const int staticMember = 10;
    };
     
    int main()
    {
        STATICDATAPTR dataPtr = &A::staticMember;
        STATICFUNCPTR funcPtr = &A::StaticFunc;
     
        cout << *dataPtr;            //直接解引用
        cout << (*funcPtr)();
     
        return 0;
    }
    复制代码

    最后注明一下。显然的,要使用(&类名::成员名)获取指向成员的指针,首先这个成员必须是对外可见的哦。即public的,不然是没有权限获取的^^。


    写到此,简单总结一下就是:

    1)静态的和普通的函数指针没啥差别;

    2)非静态的加一个类局限一下就可以。

     

    不知道以后还会不会有函数指针相关的内容,先到此完结吧。

    有错误欢迎指正,我会及时改动^^。

    (完)



  • 相关阅读:
    POJ2976 Dropping tests 01分数规划
    POJ 2728 Desert King 01分数规划,最优比率生成树
    codeforces 675E Trains and Statistic 线段树+贪心统计
    codeforces 675D Tree Construction set
    UVA 11235Frequent values(RMQ)
    FZU 2105Digits Count(线段树 + 成段更新)
    HDU 4006The kth great number(K大数 +小顶堆)
    UVA 624CD(01背包输出 + 输出路径)
    HDU 1796How many integers can you find(容斥原理)
    HDU 1817Necklace of Beads(置换+Polya计数)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5411598.html
Copyright © 2011-2022 走看看