【C++】指向类成员函数的函数指针

定义:类成员函数指针(member function pointer),是 C++ 语言的一类指针数据类型,用于存储一个指定类具有给定的形参列表与返回值类型的成员函数的访问信息。

基本上要注意的有两点:

1、函数指针赋值要使用 &
2、使用 .* (实例对象)或者 ->*(实例对象指针)调用类成员函数指针所指向的函数
下面看两个例子:

A) 类成员函数指针指向类中的非静态成员函数
对于 nonstatic member function (非静态成员函数)取地址,获得该函数在内存中的实际地址

对于 virtual function(虚函数), 其地址在编译时期是未知的,所以对于 virtual member function(虚成员函数)取其地址,所能获得的只是一个索引值

//指向类成员函数的函数指针
#include <iostream>
#include <cstdio>
using namespace std;
 
class A
{
    public:
        A(int aa = 0):a(aa){}
 
        ~A(){}
 
        void setA(int aa = 1)
        {
            a = aa;
        }
        
        virtual void print()
        {
            cout << "A: " << a << endl;
        }
 
        virtual void printa()
        {
            cout << "A1: " << a << endl;
        }
    private:
        int a;
};
 
class B:public A
{
    public:
        B():A(), b(0){}
        
        B(int aa, int bb):A(aa), b(bb){}
 
        ~B(){}
 
        virtual void print()
        {
            A::print();
            cout << "B: " << b << endl;
        }
 
        virtual void printa()
        {
            A::printa();
            cout << "B: " << b << endl;
        }
    private:
        int b;
};
 
int main(void)
{
    A a;
    B b;
    void (A::*ptr)(int) = &A::setA;
    A* pa = &a;
    
    //对于非虚函数,返回其在内存的真实地址
    printf("A::set(): %p\n", &A::setA);
    //对于虚函数, 返回其在虚函数表的偏移位置
    printf("B::print(): %p\n", &A::print);
    printf("B::print(): %p\n", &A::printa);
 
    a.print();
 
    a.setA(10);
 
    a.print();
 
    a.setA(100);
 
    a.print();
    //对于指向类成员函数的函数指针,引用时必须传入一个类对象的this指针,所以必须由类实体调用
    (pa->*ptr)(1000);
 
    a.print();
 
    (a.*ptr)(10000);
 
    a.print();
    return 0;
}

执行以上代码,输出结果为:

A::set(): 0x8048a38
B::print(): 0x1
B::print(): 0x5
A: 0
A: 10
A: 100
A: 1000
A: 10000

B) 类成员函数指针指向类中的静态成员函数

#include <iostream>
using namespace std;
 
class A{
public:
    
    //p1是一个指向非static成员函数的函数指针
    void (A::*p1)(void);
    
    //p2是一个指向static成员函数的函数指针
    void (*p2)(void);
    
    A(){
        /*对
         **指向非static成员函数的指针
         **和
         **指向static成员函数的指针
         **的变量的赋值方式是一样的,都是&ClassName::memberVariable形式
         **区别在于:
         **对p1只能用非static成员函数赋值
         **对p2只能用static成员函数赋值
         **
         **再有,赋值时如果直接&memberVariable,则在VS中报"编译器错误 C2276"
         **参见:http://msdn.microsoft.com/zh-cn/library/850cstw1.aspx
         */
        p1 =&A::funa; //函数指针赋值一定要使用 &
        p2 =&A::funb;
        
        //p1 =&A::funb;//error
        //p2 =&A::funa;//error
        
        //p1=&funa;//error,编译器错误 C2276
        //p2=&funb;//error,编译器错误 C2276
    }
    
    void funa(void){
        puts("A");
    }
    
    static void funb(void){
        puts("B");
    }
};
 
int main()
{
    A a;
    //p是指向A中非static成员函数的函数指针
    void (A::*p)(void);
    
    (a.*a.p1)(); //打印 A
    
    //使用.*(实例对象)或者->*(实例对象指针)调用类成员函数指针所指向的函数
    p = a.p1;
    (a.*p)();//打印 A
    
    A *b = &a;
    (b->*p)(); //打印 A
    
    /*尽管a.p2本身是个非static变量,但是a.p2是指向static函数的函数指针,
     **所以下面这就话是错的!
     */
//    p = a.p2;//error
    
    void (*pp)(void);
    pp = &A::funb;
    pp(); //打印 B
    
    return 0;
}
发布了423 篇原创文章 · 获赞 14 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/LU_ZHAO/article/details/105480506