雪千渔Blog

  • 首页
  • Coding
    • dotNet
    • C++
    • Lua
    • Visual Basic
    • Java
    • Android
    • Web
  • DCC
    • Maya
    • Maya-Plug
    • AfterEffect
    • AfterEffect-Plug
    • PhotoShop-Plug
  • GameDev
    • Unity3D
    • UnrealEngine
    • 经验杂谈
    • 游戏设计
    • 自研引擎
    • 效果实现
  • Graphics
    • OpenGL
    • Vulkan
    • 计算机图形学
  • 其他
    • 乱七八糟
    • 软件工具
    • 留言板
    • 自制素材
    • 关于我
雪千渔blog
唯有热爱,能抵漫长岁月
  1. 首页
  2. Coding
  3. C++
  4. 正文

C++自制反射系统(一):类型反射结构

2021年8月6日 1513点热度 3人点赞 0条评论

Contents

前言

Reflection:反射,这一特性在许多主流语言中都能找到,可以在运行时动态的获取类型信息。

一些人认为在cpp中编程时,可以规避掉使用反射,转而用模板来实现,或者使用反射就是程序设计出现了问题;要么就是有关于运行时反射对于性能影响,都用到反射了还不如去用Java之类的说辞。但我认为,在cpp中还是有一些需求是可以用到运行时反射的:对象的序列化与反序列化、可以通过字符串查找类型与创建对象、运行时判断继承关系等功能。

分析

反射信息属于一种元数据,这种元数据储存了类型相关的信息,如:类型名、基类、字段、方法、以及字段方法中的类型。这种在获取后也是储存在类中的,例如类的反射类型就是Type(C#)或Class(Java),字段的反射信息类就是FieldInfo等等。

以下文章储存反射信息的类将使用Type。

一般有三种方式获取反射信息Type实例:

第一种:使用字符串获取,Type::GetType("xxclass") 或 Class::forName("xxclass") 等等形式。

第二种:首先需要一个Object基类,该Object类的实例可以动态的获取一个元数据实例Type。也就是obj.GetType()

第三种:直接通过类型来获取,typeof(Object) 或 Object.class 等。

实现

基本实现思路:使用全局变量初始化变量的自定义结构体构造函数,通过模板元编程与手动传入等手段获取类型信息,最后向全局元数据信息表提交数据。

类型基础设计

在Object中编写一个私有静态的,用于获取类型信息的方法。

class Object
{
    friend class Type;
private:
    static Type* __meta_type();
};

声明Type类型:

class Type final : public Object
{
    using c_inst_ptr_t = Object * (*)(const ParameterPackage&);
private:
    int id_;
    string name_;
    int structure_size_;
    Type* base_;
    c_inst_ptr_t c_inst_ptr_;
    const std::type_info& typeinfo_;
};

该Type类型记录了类型id,名字,sizeof的结果,基类对象指针,动态创建对象的工厂方法函数指针,标准库的type_info。

类型信息提交

那么如何生成这些Type实例呢?

使用在进main函数前,所有的全局变量都会初始化完毕这个特性,创建一个全局变量。这个全局变量将会自动收集相关信息后,提交或者注册到一个全局的Type表当中。我们可以轻松的利用C++17标准的静态内联变量来实现此功能。

class Object
{
 friend class Type;
private:
    static Type* __meta_type();
    static inline struct _ObjectInit {
        _ObjectInit() {
            Object::__meta_type();
        }
    } _object_init;
};

静态的成员和全局变量本质是相同的,只不过静态成员的作用域与访问权限有所区别,所以依然可以参与全局的初始化。

该变量使用了自定义结构体类型,将会在初始化时自动构造。

Type* Object::__meta_type()
{
    static int id = -1;
    if (id == -1) {
        id = Type::Register(CreateInstance, nullptr, _T("JxCoreLib::Object"), typeid(Object), sizeof(Object));
    }
    return Type::GetType(id);
}

生成一个静态变量id,默认为-1,代表没注册过该类型,如果不为-1,可以直接从Type中通过id快去获取类型。

向Type提交了

  1. 创建对象工厂方法的函数指针
  2. 基类Type,因为Object没有基类,所以nullptr
  3. 类型的名字,前面带上命名空间
  4. 标准库的类型信息
  5. 类型的大小

在Register之后返回一个内部Id,通过这个Id可以快速的获取Type实例,类似于缓存的作用。

实例对象获取Type

接下来在Object中添加一个虚函数:

class Object
{
    friend class Type;
private:
    static Type* __meta_type();
    static inline struct _ObjectInit {
        _ObjectInit() {
            Object::__meta_type();
        }
    } _object_init;

    virtual Type* get_type() const;
};

实现:

Type* Object::get_type() const
{
    return __meta_type();
}

使用样例:

Object obj;
Type* type = obj.GetType();

类型获取Type

在Type中添加模板函数

template<typename T>
static inline Type* Typeof()
{
    return T::__meta_type();
}

虽然__meta_type是类型的私有成员,但是Type是Object的友元类,可以直接访问。

另外在全局声明一个,更加方便使用:

template<typename T>
Type* cltypeof()
{
    return Type::Typeof<T>();
}

因为typeof关键字在g++中作为编译器扩展存在,可能会发生冲突,所以前面加了cl。

使用样例:

assert( Object().GetType() == cltypeof<Object>() )

字符串获取Type

字符串获取就是对全局Type表的遍历,找到对应的名字后返回。

Type* Type::GetType(const string& str)
{
    for (auto& item : *g_types) {
        if (item->get_name() == str) {
            return item;
        }
    }
    return nullptr;
}

 

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: cpp 反射
最后更新:2021年8月16日

JomiXedYu

独游开发者 & 技术美术

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

JomiXedYu

独游开发者 & 技术美术

最新 热点 随机
最新 热点 随机
HLSL对Vulkan的适应性以及伪语义绑定 GPU呈现模式与垂直空白 自研引擎PulsarEngine的Shader编译流程 UE材质Custom节点与HLSL的HACK操作 UE5出现D3D12崩溃报错解决方案 游戏引擎脚本绑定的三种写法与利弊
HLSL对Vulkan的适应性以及伪语义绑定
自制神户小鸟KanbeKotori三维模型 LuaSharp:适用于.Net开发者的Lua框架 gitbook两个bug解决方法与修复工具 Key社咖啡贴图psd MonoSingleton生命周期与移动构造 AfterEffect 渲染设置模板与输出模块模板
友情链接
  • DorinXL
  • 小博博客
  • 秋橘斋

COPYRIGHT © 2014-2023 雪千渔Blog. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

辽ICP备20006894号-1