一,前言
由于看到了类似的写法,都用到了object_dynamic_cast_assert函数,所以分析下。
二,源码分析
- 看到如下代码的写法,很眼熟
CortexMBoardState *board = CORTEXM_BOARD_STATE(machine);
machine 的类型是MachineState *
#define CORTEXM_BOARD_STATE(obj) \
OBJECT_CHECK(CortexMBoardState, (obj), TYPE_CORTEXM_BOARD)
#define OBJECT_CHECK(type, obj, name) \
((type *)object_dynamic_cast_assert(OBJECT(obj), (name), \
__FILE__, __LINE__, __func__))
- 展开后就是
((CortexMBoardState *)object_dynamic_cast_assert(((Object *)((machine))), ("cortexm:" "machine"), __FILE__, __LINE__, __func__))
- 主要分析object_dynamic_cast_assert函数
Object *object_dynamic_cast_assert(Object *obj, const char *typename,
const char *file, int line, const char *func)
{
……
inst = object_dynamic_cast(obj, typename);
……
}
Object *object_dynamic_cast(Object *obj, const char *typename)
{
if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
return obj;
}
return NULL;
}
- 所以最主要的是object_class_dynamic_cast函数
ObjectClass *object_class_dynamic_cast(ObjectClass *class,
const char *typename)
{
……
/* 根据name直接找class */
type = class->type;
if (type->name == typename) {
return class;
}
/* 根据name来找到Type */
target_type = type_get_by_name(typename);
if (type->class->interfaces &&
type_is_ancestor(target_type, type_interface)) {
……
}
/* 根据父类的name来找type */
else if (type_is_ancestor(type, target_type)) {
ret = class;
}
}
上面我加的注释其实描述的不对,应为用了找class,其实class是传入的参数,是通过object_get_class(obj)传入的obj->class,而object是应用层machine将类型MachineState*强转为object*的。所以这里不能说找class,只能说check class。所以从宏定义的名字OBJECT_CHECK也看出这个函数的含义是检查用的。
object_dynamic_cast的返回类型是Object*,能赋值给CortexMBoardState*吗?直接赋值不可以,但是右边的值强转为object*是可以的,因为CortexMBoardState的首个元素就是Object类型的对象。
若我不检查,直接CortexMBoardState *board = (Object *)machine来赋值也可以,但是若参数machine中的object不存在为Null那么就会存在问题,所以用了这个OBJECT_CHECK来封装。
三,小结
这种就类似c++中的基类转为派生类,说不定c++源码的实现也是这样的设计,又学习到一招,这就是我喜欢底层的原因,因为能更加深入的了解设计方法及运行机制。