📌往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)
①📖 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
②📖嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
③📖 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
④📖 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
⑤📖 记录一场鸿蒙开发岗位面试经历~
⑥📖 持续更新中……
一、前言
在上一篇中,针对common的头文件以及实现进行了分析,本文先对上一篇的内容进行补充。再对新的iunknown部分进行分析。
二、common补充分析
在vector中按元素内容查找
/*
函数功能:根据element查询元素下标
函数参数:@vector:vector对象
@element:待查询的元素
函数返回:成功 返回元素下标,失败 返回INVALID_INDEX
详细描述:
1.判断vector对象的函数指针key是否为NULL,若不为NULL,则将element转化为key值。
2.调用VECTOR_FindByKey根据键值查询
3.若函数指针key为NULL则传element,否则传入计算后的key值
*/
int16 VECTOR_Find(Vector *vector, const void *element)
{
//参数检查
if (vector == NULL || element == NULL) {
return INVALID_INDEX;
}
//将通过element查找转化为通过键值查找
return VECTOR_FindByKey(vector, (vector->key == NULL) ? element : vector->key(element));
}
获取vector的容量及元素个数
/*
函数功能:根据键值查询元素下标
函数参数:@vector: vector对象
@key: 指定键值
函数返回:成功 返回元素下标,失败 返回INVALID_INDEX
详细描述:
1.首先检查参数
2.遍历vector的data,首先判断vector的函数指针key是否为NULL
3.若不为NULL,则计算元素对应的key值,并赋值给first,否则用当前元素赋值
4.有两种方式进行匹配,第一种直接判断first与传入的key是否相等,第二种通过compare函数比较
5.若匹配成功则返回相应下标
*/
int16 VECTOR_FindByKey(Vector *vector, const void *key)
{
//参数检查
if (vector == NULL || key == NULL) {
return INVALID_INDEX;
}
int16 i;
//遍历vector的data
for (i = 0; i < vector->top; ++i) {
//跳过data[i]为NULL的
if (vector->data[i] == NULL) {
continue;
}
//vector对象的key为NULL时first为元素指针,不为空时first为元素对应的key值
void *first = (vector->key != NULL) ? vector->key(vector->data[i]) : vector->data[i];
//判断first与key的指向是否相同
if (first == key) {
//相同,则找到指定元素,返回下标
return i;
}
//first与key的指向不相同,进一步通过键值比较函数判断
if (vector->compare == NULL || first == NULL) {
//若键值比较函数为NULL,或者first指向NULL,跳出本次循环
continue;
}
//通过比较函数比较first和key指向的值
if (vector->compare(first, key) == 0) {
return i;
}
}
return INVALID_INDEX;
}
获取vector的容量及元素个数
//获取vector对象中data的大小,包括NULL
int16 VECTOR_Size(Vector *vector)
{
if (vector == NULL) {
return INVALID_INDEX;
}
//返回top值,等于vector中最后一个元素下标+1
return vector->top;
}
//获取vector对象中data实际占用空间,即元素个数,不包括NULL
int16 VECTOR_Num(Vector *vector)
{
if (vector == NULL) {
return INVALID_INDEX;
}
//vector中元素已占用的个数top与vector已释放元素的个数free的差值
return vector->top - vector->free;
}
三、iunknown头文件
接下来进入本文的正题,对iunknown的头文件进行分析。头文件位于distributedschedule_samgr_lite\interfaces\kits\samgr\iunknown.h。iunknown为系统功能的外部功能提供基类和默认实现。
- 结构体分析
//结构体的声明,包含QueryInterface函数指针、AddRef函数指针、Release函数指针
struct IUnknown {
//查询指定版本接口的子类对象
int (*QueryInterface)(IUnknown *iUnknown, int version, void **target);
//添加引用计数
int (*AddRef)(IUnknown *iUnknown);
//释放对接口的引用
int (*Release)(IUnknown *iUnknown);
};
typedef struct IUnknownEntry {
//接口版本信息
uint16 ver;
//接口的引用计数。
int16 ref;
//IUnknown接口成员
IUnknown iUnknown;
} IUnknownEntry;
- 宏定义分析
//定义用于继承IUnknown接口的宏
//当开发IUnknown类的子类时,可以使用这个宏来继承IUnknown接口结构
#define INHERIT_IUNKNOWN \
int (*QueryInterface)(IUnknown *iUnknown, int version, void **target); \
int (*AddRef)(IUnknown *iUnknown); \
int (*Release)(IUnknown *iUnknown)
//定义用于继承实现IUnknown接口的类的宏
//当开发一个实现了IUnknown接口的类的子类时,可以使用这个宏继承IUnknown实现类的结构
#define INHERIT_IUNKNOWNENTRY(T) \
uint16 ver; \
int16 ref; \
T iUnknown
//定义初始化IUnknown接口的默认宏
//当创建IUnknown接口的子类对象时,可以使用此宏将IUnknown接口的成员初始化为默认值
#define DEFAULT_IUNKNOWN_IMPL \
.QueryInterface = IUNKNOWN_QueryInterface, \
.AddRef = IUNKNOWN_AddRef, \
.Release = IUNKNOWN_Release
//定义用于初始化实现IUnknown接口的类的宏。
//当创建实现IUnknown接口的类的子类对象时,可以使用这个宏将IUnknown实现类的成员初始化为默认值
#define IUNKNOWN_ENTRY_BEGIN(version) \
.ver = (version), \
.ref = 1, \
.iUnknown = { \
DEFAULT_IUNKNOWN_IMPL
四、结语
本篇文章首先对common剩余部分的内容进行了分析,然后对iunknown头文件中的一些内容进行介绍。要想深入的理解iunknown是什么以及有什么作用,可以继续阅读下一篇文章,关于iunknown的实现分析。