C++中的类成员指针

 

写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文!

本博客全网唯一合法URL:http://www.cnblogs.com/acm-icpcer/p/6729273.html

 

 

C++中的类成员指针

 

  在上一篇文章中我提到了C++中的函数指针。那么如果想定义一个指向类数据成员或者函数成员的指针,又该怎么办呢?

  本质上讲和之前我提到的写法没有什么不同,只不过是要加上域定义而已。

 

1.类数据成员指针

  例如,对于下面的类A:

class A
{
public:
    int x;
    int sayhello()
    {
        cout<<"hello world"<<endl;
    }
};

  假如我想定义一个指向数据成员x的指针,则:

  int A::*pointer1 = &A::x;

  很明显,去掉域定义其实就是普通的指针定义:int pointer1=&x;

  那么,如果用typedef来简化语法就是:

  typedef int A::*int_pointer;

  int_pointer pointer2 = &A::x;

  两者是等价的。

  调用指针时则为:

    A a;
    a.*pointer1 = 6;
    ++(a.*pointer2);
    cout << &a->*pointer1 << endl;

  结果为7。(注意:必须声明一个A的对象才可以调用类数据成员指针)

  那么这个类数据成员指针究竟是地址还是什么呢?

  为了搞清楚,我们就把它打出来看看吧:

  cout << pointer1 << endl << pointer2 << endl;

   结果是1    1。

  这是什么意思呢?实际上,类数据成员指针只是相对于对象在内存中初始地址的一个偏移量,也就是说,它是一个相对地址。

 

2.类函数成员指针

  现在,我们讨论一下类函数成员指针的定义和使用。我们的讨论建立在以下类A和类B的基础上来讲:

class A
{
private:
    int y;
public:
    double w;
    int x;
    int sayhello()
    {
        cout<<"hello world"<<endl;
    }
};

class B:public A
{

};

  类成员函数指针定义:

  int (A::*classAfunctionpointer1)();

  classAfunctionpointer1 = &A::sayhello;

  可以看到,这其实也是在普通的全局函数指针前面加上了一个域定义而已(普通全局函数指针:int (*classAfunctionpointer1)();)。

  那么,如果用typedef来简化语法就是:

  typedef int (A::*FP)();

  FP classAfunctionpointer2 = &A::sayhello;

  调用时都是一样的:

  (a.*classAfunctionpointer1)();

  (a.*classAfunctionpointer2)();

  或者

  (&a->*classAfunctionpointer1)();

  (&a->*classAfunctionpointer2)();

  结果都是打印出hello world。(注意:类成员函数指针在使用前必须先声明一个对象)

  那么,类B继承了类A,理论上讲B也可以使用A的指针:

  B b;

  (b.*classAfunctionpointer1)();

  确实可以,结果也是打印出hello world。

  那么这又是为什么呢?

  实际上,类成员函数的地址是绝对的,因为类成员函数是定义在一个固定的代码区中。当年使用不同的对象去调用同一个类成员函数的时候,本质上,编译器会把该对象的this指针默认加在该成员函数的形参列表中,以便让函数明白是谁在调用它。所以不同的对象去调用同一个类成员函数的时候,编译器才能理解并作出反应。

  

3.示例代码

  好了,根据上面讲到的所有基础知识,我给出如下程序:

#include<iostream>
using namespace std;

class A
{
private:
    int y;
public:
    double w;
    int x;
    int sayhello()
    {
        cout<<"hello world"<<endl;
    }
};

class B:public A
{

};

typedef int A::*int_pointer;
typedef int (A::*FP)();

int main()
{
    int A::*pointer1 = &A::x;
    int_pointer pointer2 = &A::x;
    A a;
    a.*pointer1 = 6;
    ++(a.*pointer2);
    cout << &a->*pointer1 << endl << pointer1 << endl << pointer2 << endl;

    double A::*pointer3 = &A::w;
    cout<<pointer3<<endl;

    B b;
    a.sayhello();
    int (A::*classAfunctionpointer1)();
    classAfunctionpointer1 = &A::sayhello;
    FP classAfunctionpointer2 = &A::sayhello;
    (a.*classAfunctionpointer1)();
    (a.*classAfunctionpointer2)();
    (&a->*classAfunctionpointer1)();
    (b.*classAfunctionpointer1)();

    return 0;
}

 

 

TZ

2017/4/18于华中农业大学

 

转载于:https://www.cnblogs.com/acm-icpcer/p/6729273.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值