C++必知必会之(16)指向成员函数的指针并非指针

本文详细介绍了在C++中获取非静态成员函数的地址、成员函数指针的使用方式、与数据成员指针的区别、逆变性、虚拟性以及如何在不同类间进行转换。同时强调了解引用和调用成员函数指针的操作符优先级。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、获取非静态成员函数的地址时,得到的不是一个地址,而是一个指向成员函数的指针。

class Shape  {

    public:

        //.....

        void moveTo (Point   newLocation );

        bool validate ( )    const;

        virtual bool draw( )   const = 0;

        //....

};

class Circle : public  Shape   {

      //.....

      bool  draw( )  const;

      //.....

};

//.....

void (Shape::*mf1) ( Point )  =  &Shape::moveTo;   //不是指针


与指向数据成员的指针一样,我们需要做的就是使用classname::*而不是*来指明所指向的函数是classname的一个成员。然而,和指向常规函数的指针不同,指向成员函数的指针可以指向一个常量成员函数:

bool ( Shape::*mf2 ) ( )  const = &Shape::validate;


2、和指向数据成员的指针的情形一样,为了对一个指向成员函数的指针进行解引用,需要一个对象或一个指向对象的指针。对于指向数据成员的指针的情形,为了访问该成员,需要将对象的地址和成员的偏移量(包含于指向数据成员的指针中)相加。对于指向成员函数的指针的情形,需要将对象的地址用作this指针的值,进行函数调用,以及作为其他用途。

Circle circ;

Shape *pShape = ˆ

( pShape->*mf2 ) ( );   //调用Shape::validate;

(circ.mf2 ) ( ) ;    //调用Shape::validate


->*和.*操作符必须加上圆括号,因为它们比()操作符优先级低,而且在调用函数之前首先应该找到这个函数。

这与在(a+b)*c之类的表达式中的括号用法类似。在该表达式中,我们希望确保较低优先级的加法在较高优先级的乘法之前执行。


3、注意,不存在什么指向成员函数的“虚拟”指针。

虚拟性是成员函数自身的属性,而不是指向它的指针所具有的属性。


mf2 = &Shape::draw;   //draw是虚函数

( pShape->*mf2 ) ( );    //调用Circle::draw

这也解释了为何一个指向成员函数的指针,通常不能被实现为一个简单的指向函数的指针。

一个指向成员函数的指针的实现自身必须存储一些信息,诸如它所指向的成员函数是虚拟的还是非虚拟的,到哪里去找到适当的虚函数表指针,从函数的this指针加上或减去的一个偏移量以及其他的一些信息。指向成员函数的指针通常实现为一个小型结构,其中包含这些信息。


解引用和调用一个指向成员函数的指针通常涉及到检查这些存储的信息,并有条件地执行适当的虚拟或非虚拟的函数调用序列。


4、和指向数据成员的指针一样,指向成员函数的指针也表现出一种逆变性,即存在从指向基类成员函数的指针到指向派生类成员函数的指针的预定义转换,反之则不然。

这很好理解:如果你考虑到基类成员函数会视图通过其this指针只访问基类成员,然而派生类函数可能会试图访问基类中不存在的成员的话。

class B  {

    public:

        void best( int val )   {  bval_ = val;   }

    private:

        int bval_;

};

class D : public B   {

   public:

       void dset ( int val )   {   dval_ = val; }

   private:

       int dval_;

};

B b;

D d;

void (B::*f1) (int)  =  &D::dset;      //错误,不存在这种反向转换

(b *f1) (12);    //访问不存在的dval成员!

void (D::*f2) (int) = &B::best;      //ok

(d.*f2)  (11);      //ok,设置继承来的bval_数据成员


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值