函数指针

@

前言:

class Thread {
public:
    Thread() {}
    ~Thread() {}

    static void testThread() {
        cout << "test thread" << endl;
    }

    static void start() {
        std::thread t1(testThread);
        t1.join();
    }
};

int main()
{
    Thread t;
    t.start();

    return 0;
}
在类内创建一个线程时,如果testThread是非静态的,则编译会报错:
reference to non-static member function must be called; did you mean to call it with no arguments?
no matching constructor for initialization of 'std::thread'
原因是由于:非静态成员函数testThread有一个隐式的参数this指针,而静态成员函数没有this指针

函数指针定义

每一个函数都占用一段内存单元,它们有一个起始地址,指向函数入口地址的指针称为函数指针。

数据类型 (*指针变量名)(参数表);

注意区别:

void (*p)(int a, int b); //p是一个指向函数的指针变量

void *p(int a, int b); //p是函数名,此函数的返回值类型为void指针

函数指针的初始化和赋值

1.定义一个函数

void fun(int a, int b) {}

2.函数指针初始化和赋值

void (*pFun)(int a, int b) = fun;

可以使用typedef
typedef void (*pFunctionType)(int a, int b);
pFunctionType pFun =  fun;
pFunctionType pFun =  &fun; // 在C/C++里函数名就是地址,所以上面两个等价,都可以给函数指针赋值。

函数调用

可以直接使用指向函数的指针调用函数

fun(5, 6);
(*pFun)(5, 6);
 (*pFunctionType)(5, 6);

注意:

  • 指向不同函数类型的指针之间不存在转换规则。
  • 可以为函数指针赋一个 nullptr或者0的整型常量表达式,表示该指针没有指向任何一个函数。

函数指针作为形参

例如:

#include<iostream>

using namespace std;
typedef int(*addFcn)(int a, int b);

int addFunction(int a, int b) {
    return (a + b);
}

void test(int a, int b, int(*pf)(int a, int b)) {
    cout << pf(a, b) << endl;
}

int main()
{    
    addFcn pf = addFunction;
    test(3, 4, pf);
    return 0;
}

/*
输出结果:7
*/

函数指针作为返回值

#include<iostream>

using namespace std;

int demo(int a, int b) {
    return a*b;
}

// ff是一个函数,有一个形参x,返回结果是一个函数指针int(*)(int,int)
int (*ff(int x))(int, int) {
    cout << x << endl;
    return demo;
}

int main()
{    
    int a = 5;
    cout << ff(2)(a, a)<< endl;
    return 0;
}
/*
输出结果:
2
25
*/

指向类的成员函数的指针

1)指向类非静态成员函数的指针

指向类非静态成员函数的指针与普通函数指针的区别在于: 不仅要匹配函数的参数类型和个数以及返回值类型,还要匹配该函数指针所属的类类型。

声明:与普通函数相比,指向类的成员函数的指针只需要在指针前加上类类型即可,格式为:

typedef 返回值 (类名::*指针类型名)(参数列表);

赋值:只需要用类的成员函数地址赋值即可,格式为:

指针类型名  指针名 = &类名::成员函数名;  //加了&,才会认为是获取函数指针,不然,编译器会认为是调用成员函数

调用:针对调用的对象是对象还是指针,分别用.和->进行调用,格式为:

(类对象.*指针名)(参数列表);
(类指针->*指针名)(参数列表);
// 注意:这里的前面一对括号是很重要的,因为()的优先级高于成员操作符指针的优先级。

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

类的静态成员是不依赖于具体对象的,所有实例化的对象都共享同一个静态成员,所以静态成员函数也没有this指针的概念。
所以,指向类的静态成员函数的指针就是普通的指针。

例子:

#include<iostream>
using namespace std;

typedef void (*STATICFUNCPTR)(int a, int b);   // 静态成员函数指针

class A;
typedef void (A::*NONSTATICFUNCPTR)(int a, int b);    //非静态成员函数指针

class A
{
public:
    void nonStaticFunc(int a, int b)
    {
        cout<< "nonStaticFunc result: " << a + b << endl;
    }

    static void staticFunc(int a, int b)
    {
        cout<< "staticFunc result: " << a * b << endl;
    }
};

int main()
{
    NONSTATICFUNCPTR nonStaticFuncPtr= &A::nonStaticFunc;
    STATICFUNCPTR    staticFuncPtr = &A::staticFunc;

    A a;
    (a.*nonStaticFuncPtr)(3, 4);        //非静态函数指针通过对象调用

    A *aPtr = new A;
    (aPtr->*nonStaticFuncPtr)(5, 6);    //非静态函数指针通过指针调用


    (*staticFuncPtr)(5, 6);    //静态函数指针调用

    return 0;
}

/*
输出结果:
nonStaticFunc result: 7
staticFunc result: 12
nonStaticFunc result: 11
staticFunc result: 30
*/

指向类的数据成员的指针

类的非静态成员变量需要判断下列两项是否一致,而静态成员不依赖this指针,不需要判断b

a)数据成员类型
b)所属的类类型

例子

#include <iostream>
using namespace std;

class A;
typedef int (A::*NONSTATICDATAPTR);      //定义类的非静态数据成员指针
typedef const int *STATICDATAPTR;        //定义类的静态数据成员指针

class A
{
public:
    A(int a):m_nonStaticData(a){}
    int    m_nonStaticData;

    static int m_staticData;
};

int A::m_staticData = 6;


int main()
{
    NONSTATICDATAPTR nonStaticDataPtr= &A::m_nonStaticData;
    STATICDATAPTR    staticDataPtr = &A::m_staticData;
    
    A a(10);
    cout << "(non static) obj: " << a.*nonStaticDataPtr << endl;        //通过对象引用

    A *aPtr = new A(100);
    cout << "(non static) pointer:" << aPtr->*nonStaticDataPtr << endl;    //通过指针引用

    cout << "(static): " << *staticDataPtr << endl;

    return 0;
}
/*输出结果:
(non static) obj: 10
(non static) pointer:100
(static): 6
*/
posted on 2020-04-14 14:20  JJ_S  阅读(435)  评论(0编辑  收藏  举报