Camera Native Framework C++语法基础之类成员函数指针

本文深入探讨了类成员函数指针的概念,包括其与普通函数指针的区别,如何定义、初始化和调用。通过示例展示了如何在类内部和外部使用成员函数指针,并解释了在Android框架中类似语法的应用,特别是在Camera服务连接过程中的使用。
摘要由CSDN通过智能技术生成

函数指针不能直接调用类的成员函数,需采取间接的方法,原因是成员函数指针与一般函数指针有根本的不同,成员函数指针除包含地址信息外,同时携带其所属对象信息

成员指针解引用操作符(.*)从对象或引用获取成员

*成员指针箭头操作符(->*)通过对象的指针获取成员

类成员函数指针定义

因为函数是一个类的成员,所以它的指针定义有别于全局函数,格式如下:

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

需要注意的地方

1) 使用typedef创建一个用户自定义类型,这个类型的名称即上述格式中的函数指针类型名称

2) 在函数指针类型名称之前需要添加类名,并加上双引号(::)

初始化方式

假设我们的一个类有如下的成员函数:

bool DriveCar(LPCTSTR pszCar);

则对应的,我们定义了如下的类成员函数指针来描述此成员函数

typedef bool (CPerson::*FP_DriveCar)(LPCTSTR pszCar);

注意这里的类标记(CPerson::),以及类成员指针前的星号(*)。

那么我们可以为该类定义函数指针类型的数据成员

FP_DriveCar m_pfnDriveCar;

这里的m_pfnDriveCar是一个数据成员,其类型为指向类成员的函数指针(FP_DriveCar)。

则该数据成员初始化方法如下:

m_pfnDriveCar = &CPerson::DriveCar;

使用类名作为前缀,指明我们需要访问CPerson类的DriveCar方法。另外,加上取地址符号(&)取得其函数地址。

调用方式

1) 在类内部

(this->*m_pfnDriveCar)(_T(“TestCar”));

2) 在类外部

CPerson person;

FP_DriveCar g_pfnDriveCar = &CPerson::DriveCar;

(person.*g_pfnDriveCar)(_T(“TestCar”));

注意的地方

1) 在类内部调用时,需要加上(this->)。

2) 在类外部调用时,需要加上对象的实例,这里即(person.)。

3) 函数指针前加上解除引号符号(*)。

总结

1) 类成员函数指针和普通全局函数指针的区别在于,需要特殊的语法(通常是加上类名)来进行定义和调用,这是因为类成员函数有一个隐藏的this参数。

2) 如果需要在类外部使用类函数指针,则目标类成员函数必须设定为public访问类型。

3) 调用时,需要显式的加上类实例(以上代码中的this→或者person.)。

Camera中涉及到此语法的地方为

template <>

struct CameraTraits<Camera>

{

    typedef CameraListener                     TCamListener;

    typedef ::android::hardware::ICamera       TCamUser;

    typedef ::android::hardware::ICameraClient TCamCallbacks;

    typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService)

        (const sp<::android::hardware::ICameraClient>&,

        int, const String16&, int, int,

        /*out*/

        sp<::android::hardware::ICamera>*);

    static TCamConnectService     fnConnectService;

};

这里我们可以看到使用全特化来限制输入类型为Camera类型,从这个萃取器我们可以拿到Camra的一些特征,比如回调等等。注意这里使用了类成员函数指针定义了一个TCamConnectService函数,并且定义fnConnectService函数指针用来引用相应的函数,这个看起来比较难理解,可参考之前的语法知识2.2来学习。

其中fnConnectService初始化在下面文件中

Z:\SA800U_Android9.0_R01_r220\frameworks\av\camera\Camera.cpp

CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =

        &::android::hardware::ICameraService::connect;

这个函数的调用是在:

Z:\SA800U_Android9.0_R01_r220\frameworks\av\camera\CameraBase.cpp

template <typename TCam, typename TCamTraits>

sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,

                                               const String16& clientPackageName,

                                               int clientUid, int clientPid)

{

    ALOGV("%s: connect", __FUNCTION__);

    sp<TCam> c = new TCam(cameraId);

sp<TCamCallbacks> cl = c;

    const sp<::android::hardware::ICameraService> cs = getCameraService();

    binder::Status ret;

    if (cs != nullptr) {

        TCamConnectService fnConnectService = TCamTraits::fnConnectService;

        ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,

                                               clientPid, /*out*/ &c->mCamera);

    }

    if (ret.isOk() && c->mCamera != nullptr) {

        IInterface::asBinder(c->mCamera)->linkToDeath(c);

        c->mStatus = NO_ERROR;

    } else {

        ALOGW("An error occurred while connecting to camera %d: %s", cameraId,

                (cs == nullptr) ? "Service not available" : ret.toString8().string());

        c.clear();

    }

    return c;

}

这里可以看到cs为getCameraService()获取,并且返回值为const sp<::android::hardware::ICameraService>,最终调用的地方ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, clientPid, /*out*/ &c->mCamera);综上所述调用的即是ICameraService中的connect函数。

这里的ICameraService为安卓的Binder跨进程调用,最终会调用到CameraService的connect函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值