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++专门做了区别对待。

    调用:调用方法也很简单,针对调用的对象是对象还是指针,分别用.和->进行调用,格式为:

    
    (类对象.*指针名)(参数列表);
    
    (类指针->*指针名)(参数列表);
    

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

    下面举个简单的例子就一目了然了:

    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的,不然是没有权限获取的^^。

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

    • 静态的和普通的函数指针没啥区别;
    • 非静态的加一个类局限一下即可。

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

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

    (完)

  • 相关阅读:
    手把手教你测之二——有信,一款网络电话
    DroidPilot V2.1 手写功能特别版
    《移动应用自动化测试现状与方向研讨会》视频
    手把手教你测——上网快鸟
    DroidPilot AutoRunner新版宣传视频
    DroidPilot参展2012香港贸发局国际资讯科技博览会
    视频: DroidPilot
    注意!用户使用自己的adb,版本必须是Android SDK 10以上
    部分厂家用户反映USB连接问题,是厂家修改了adb导致,解决方法:
    软件简单介绍
  • 原文地址:https://www.cnblogs.com/lanqiu5ge/p/9472220.html
Copyright © 2011-2022 走看看