关于类成员函数指针

284 阅读2分钟

类成员函数指针指向类中的非静态成员函数时,有如下两种情况:

* 对于nonstatic member function (非静态成员函数)取地址,获得该函数在内存中的实际地址
* 对于virtual function(虚函数),其地址在编译时期是未知的,所以对于virtual member function
(虚成员函数)取其地址,所能获得的只是一个索引值。

举例:

//指向类成员函数的函数指针
#include <iostream>
#include <cstdio>
using namespace std;

class A
{
public:
    A(int aa = 0) : a(aa){}
    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){}

    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

由此引出一个问题,对于c++ 11中的std::bind(),如果绑定的是一个类非静态成员函数,则一定是 &class::mem_func,而不能是class::mem_func,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在前面添加&; 而普通函数做实参时,会隐式转换成函数指针。区别就在于此。