普通函数指针、成员变量指针与成员函数指针

普通函数指针、成员变量指针与成员函数指针

(一)普通函数指针

首先先说普通函数指针,对于函数指针总是与指针函数混淆,那么他们的区别在哪呢?

1、指针函数

 int* fint a;int b)  //函数名为f,返回值为int类型的指针

简单来说,就是指针函数就是返回一个地址给调用者,用于需要地址的情况。

2、函数指针

int (*f)(int a, int b); // 声明函数指针

其实就是函数指针的函数名是一个指针,即函数名前面有一个指针类型的标志型号*”。

 

函数指针赋值(函数地址)。即f = &Function

函数指针调用。x = (*f)(参数);

3、typedef函数指针

1)理解

    typedef void (*pHello)();

int main(int argc, char *argv[])

{

    //int (*fAbc)(int axc);

    //fAbc=&abc;

    //cout<<(*fAbc)(1)<<endl;

    void (*pf)();

    pf = &hello;

    (*pf)();

    //pf();

    pHello p = &hello;

    (*p)();

    return 0;

}

connect代码中,使用了typedef void (*pHello)();意思就是定义了一个函数指针类型怕,之后每处用到p都是一个类型,代表void(*)()这个函数指针。pHello q等效于void*q();

再举一个例子:typedef int (*pF)(int);表示指向一个返回值为int,参数为int的函数。

实际上,在这里typedef就是定义了一个新的类型,定义了phello类型,并且这种类型为指向某种函数的指针,以后可以向使用intchar一样的使用phello了。至于分析这种形式的定义,可以去掉typedef和别名剩下的就是原变量的类型。例如:void (*)()

(2)使用:

    void (*pf)();

    pf = &hello;

    (*pf)();

或者pHello p = &hello;

(*p)();

在这里,如果pf=&hello改为hello,将会报错,输出效果不变,因为函数名就代表函数的首地址。

(二)成员变量指针

1、成员变量指针分为非静态成员指针和静态成员指针。

类成员变量指针,实际上并不是真正意义上的指针,即它并不是指向内存中某个地址,而是该成员变量与对象指针的偏移量。该偏移量只有附着在某个具体对象,才能指向对象成员变量的具体地址。

而对于静态成员的指针,其值就是指向内存中数据区某个地址,就是真正意义上的指针,因为静态成员属于类范围,不属于某个对象。

2、定义与声明

声明:typedef int A::* MemberPointer; //一定注意加域名,MemberPointerint *A类型的一个别名

定义:MemberPointer pV;等价于int A::* pV;

 

例:

class A{

    public:

    int x;

};

   int main(int argc, char *argv[])

{

MemberPointer pV;//成员变量指针的定义,等价于int A::* pV;

    pV = &A::x ;

    A a;

    a .* pV=1;//等价于a.x=1;

    cout << &a ->* pV << endl;

    return 0;

}

(三)成员函数指针

1、理解

非静态成员函数的指针,其值就是指向一块内存地址。但是指针不能直接调用,它需绑定到一个对象才能调用。

其实成员函数指针与普通函数指针的区别就是成员函数指针的声明要加上类的限制,编译器会在编译的时候在函数指针队形的函数调用中加上this指针,所以类成员函数不能单独调用,要与类对象配合使用。例如:typedef void (Child::*ChildMemberFunctionPointer)();

2、使用

int main(int argc, char *argv[])

{

    Person someone;

    Child xiaoming;

    PersonMemberFunctionPointer pp;

    pp = &Person::sayHello;

    (someone .* pp)();

    (xiaoming.*pp)();

    //pp=&Child::sayHello;(不能运行,需要强制转换)

    ChildMemberFunctionPointer cp = &Child::sayHello;

    (xiaoming.*cp)();

    runfuncName(&xiaoming,pp);

    PersonMemberFunctionPointer pp2 = &Person::sayName;

    (someone.*pp2)();

    (xiaoming.*pp2)();//必须是公开继承,才有权限

    return 0;

}

其中 pp = &Person::sayHello;(someone .* pp)()也就是等价于 (&someone ->* pp)();也等价于 someone.sayHello();

 

(四)总结:

1成员函数指针与普通函数指针的区别

成员函数指针的声明要加上类的限制,编译器会在编译的时候在函数指针队形的函数调用中加上this指针,所以类成员函数不能单独调用,要与类对象配合使用。

2pp = &Person::sayHello;调用类中非静态成员函数的时候,为什么使用的是类名::函数名,而不是实例名::函数名?

因为类名是域的概念,而变量名不是,使用雷明才可以找到函数代码所放置的位置,调用该函数。

3::为作用域运算符,其中::x代表全局作用域。

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/ningmengccccc/article/details/80684732