曾子曰:吾日三省吾身——为人谋而不忠乎?与朋友交而不信乎?传不习乎?

引言

上一篇我们谈到了在游戏引擎,或者在程序和高级编程语言中,设计一个统一对象模型得到的好处,和要付出的代价,以及在UE里是怎么对之尽量降低规避的。那么从本篇开始,我们就开始谈谈如何开始构建这么一个对象模型,并在此之上逐渐扩展以适应引擎的各种功能需求的。

众所周知,一般游戏引擎最底层面对的都是操作系统API,硬件SDK,所能借助到的工具也往往只有C++本身。所以考虑从原生的C++基础上,搭建对象系统,往往得从头开始造轮子,最底层也是最核心的机制当然必须得掌控在自己的手中,以后升级改善增加功能也才能不受限制。

那么,从头开始的话,Object系统有那么多功能:GC,反射,序列化,编辑器支持……应该从哪一个开始?哪一个是必需的?GC不是,因为大不了我可以直接new/delete或者智能指针引用技术,毕竟别的很多引擎也都是这么干的。序列化也不是,大不了每个子类里手写数据排布,麻烦是麻烦,但是功能上也是可以实现的。编辑器支持,默认类对象,统计等都是之后额外附加的功能了。那你说反射为何是必需的?大多数游戏引擎用的C++没有反射,不也都用得好好的?确实也如此,不利用反射的那些功能,不动态根据类型创建对象,不遍历属性成员,不根据名字调用函数,大不了手写绕一下,没有过不去的坎。但是既然上文已经论述了一个统一Object模型的好处,那么如果在Object身上不加上反射,无疑就像是砍掉了Object的一双翅膀,让它只能在地上行走,而不能在更宽阔空间内发挥威力。还有另一个方面的考虑是,反射作为底层的系统,如果实现完善了,也可以大大裨益其他系统的实现,比如有了反射,实现序列化起来就很方便了;有没有反射,也关系到GC实现时的方案选择,完全是两种套路。简单举个例,反射里对每个object有个class对象保存信息,所以理论上class身上就可以保存所有该类型的object指针引用,这个信息GC就可以利用起来实现一些功能;而没有这个class对象的话,GC的实现就得走别的方案路子了。所以说是先实现反射,有了一个更加扎实的对象系统基础后,再在此之上实现GC才更加的明智。

类型系统

虽然之上一直用反射的术语来描述我们熟知的那一套运行时得到类型信息的系统,动态创建类对象等,但是其实“反射”只是在“类型系统”实现之后的附加功能,人们往往都太过注重最后表露的强大功能,而把朴实的本质支撑给忘记了。想想看,如果我实现了class类用来