【UE 反射】反射的原理是什么?如何使用机制?

VIP【UE 反射】反射的原理是什么?如何使用机制?
静态类型检查确保了类型的早期一致性和高效的代码执行,但减少了灵活性。动态类型检查提供了更大的灵活性,但增加了运行时的开销和潜在的错误。反射作为一种动态特性,无论是在静态类型语言还是动态类型语言中,都提供了强大的运行时类型操作能力,但也伴随着性能和安全性方面的权衡。通过理解这些联系,开发者可以在不同的编程语言和应用场景中选择适合的类型检查方式和反射机制,以实现所需的动态行为和灵活性,同时保证性能和安全性。
开通可读全文 ·6k 人阅读
最低0.47元/天 解锁文章

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:UE虚幻引擎专栏
  • 💥 标题:【UE 反射】反射的原理是什么?如何使用机制?
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!
  • 🎈 最后:文章作者技术和水平有限,如果文中出现错误,希望大家能指正,同时有问题的话,欢迎大家留言讨论。

0 拓展

在开始介绍反射之前,我想先了解下不同的语言,不同的类型检查机制和反射的联系。以及偏移量在反射中的作用是什么。(这部分知识有利于反射机制的深入理解)

官方参考文章

0.1 静态类型检查

静态类型检查 是在 编译时 对程序中的所有变量和表达式进行类型检查,以确保每个操作数、变量、函数调用等的类型都是一致和兼容的。其中C、C++、Java、C#都是静态类型检查的语言。其主要原理可以通过以下几个方面来解释:

0.1.1 静态类型检查的主要原理

  1. 类型声明和定义
    在静态类型语言中,每个变量、函数参数和返回值等的类型在代码编写时就已经明确指定。这些类型信息是编译器进行类型检查的基础。

    int a = 10;         // 变量a的类型是int
    double b = 20.5;    // 变量b的类型是double
    
  2. 符号表(Symbol Table)
    编译器在编译过程中维护一个符号表,用于存储所有变量、函数及其类型信息。符号表在语法分析阶段创建,并在语义分析阶段进行扩展和检查。

  3. 类型推导
    有些静态类型语言支持类型推导,编译器可以根据上下文自动推导出变量的类型(如C++中的auto关键字)。

    auto x = 10;       // 编译器推导x的类型为int
    auto y = 20.5;     // 编译器推导y的类型为double
    
  4. 类型检查
    编译器在编译过程中对所有表达式和语句进行类型检查,以确保类型一致性。例如,变量赋值时检查类型兼容性,函数调用时检查参数类型匹配,运算符操作时检查操作数类型。

    int a = 10;
    double b = 20.5;
    a = b;    // 编译器会警告或错误,类型不兼容
    
    void foo(int x) {
         
          }
    foo(b);   // 编译器会警告或错误,类型不兼容
    
  5. 类型转换
    静态类型语言通常支持显式类型转换和隐式类型转换。编译器在类型转换时进行检查,确保转换是合法的。

    int a = 10;
    double b = static_cast<double>(a);  // 显式类型转换
    double c = a;                       // 隐式类型转换
    

0.1.2 编译器的工作流程

编译器的工作流程通常分为以下几个阶段,每个阶段都会涉及类型检查:

  1. 词法分析(Lexical Analysis)
    将源代码转换为一系列标记(tokens),这些标记代表代码中的基本元素,如关键字、标识符、操作符等。

  2. 语法分析(Syntax Analysis)
    根据语法规则将标记组织成语法树(parse tree 或 AST, Abstract Syntax Tree),表示程序的结构。

  3. 语义分析(Semantic Analysis)
    进行类型检查,确保每个操作符和操作数的类型一致。建立和维护符号表,跟踪变量和函数的类型信息。

  4. 中间代码生成(Intermediate Code Generation)
    将语法树转换为中间表示(IR, Intermediate Representation),这种表示比源代码更接近机器代码,但仍然与具体机器无关。

  5. 优化(Optimization)
    对中间代码进行各种优化,提高程序执行效率。

  6. 目标代码生成(Code Generation)
    将优化后的中间代码转换为目标机器代码。

0.1.3 静态类型检查的优点和缺点

优点

  • 提高性能: 静态类型检查消除了运行时类型检查的开销,生成的代码更高效。
  • 早期错误检测: 类型错误在编译时被捕捉,减少了运行时错误的发生。
  • 代码可维护性: 明确的类型定义提高了代码的可读性和可维护性。

缺点

  • 灵活性较低: 类型必须在编译时确定,减少了代码的灵活性和动态性。
  • 开发速度较慢: 需要显式地声明类型,增加了编码工作量。

0.1.4 示例

以下是一个C++代码示例,演示了静态类型检查的基本原理:

#include <iostream>

int add(int a, int b) {
   
   
    return a + b;
}

int main() {
   
   
    int result = add(5, 3); // 编译时确定类型
    std::cout << "Result: " << result << std::endl;
    return 0;
}

在这个例子中,变量result的类型在编译时确定为int,函数add的参数类型也在编译时确定为int,编译器会在编译时检查这些类型信息,确保类型一致性和正确性。

通过静态类型检查,编译器可以在编译阶段发现并修正许多潜在的错误,提高程序的可靠性和性能。这种设计使得静态类型语言在大型、复杂的系统中具有显著的优势。

0.1.5 C++也可以在运行时类型检查

虽然C++主要依赖静态类型检查来确保类型安全性和性能,但它也提供了多种机制支持运行时类型检查,如RTTI、自定义类型检查机制和第三方库。通过这些机制,开发者可以在运行时识别和处理类型信息,实现更灵活和动态的程序行为。这种组合使得C++在需要高性能和类型安全性的同时,也能在某些场景下提供必要的动态类型处理能力。

接下来就详细介绍一下RTTI

RTTI(Runtime Type Information,运行时类型信息)是C++的一种机制,它允许程序在运行时获得类型相关的信息。RTTI的主要原理基于虚函数表(vtable)和类的继承关系。下面是RTTI的基本原理和实现机制:

RTTI基本原理
  1. 虚函数表(vtable)
    当一个类包含虚函数时,编译器会为这个类生成一个虚函数表(vtable),其中包含了所有虚函数的指针。每个包含虚函数的类实例都有一个指向这个虚函数表的指针(称为vptr)。

  2. RTTI数据
    RTTI信息也会存储在虚函数表中。具体来说,编译器会在虚函数表中加入指向类型信息(如std::type_info对象)的指针。这个指针通常在虚函数表的某个固定位置。

RTTI的实现

RTTI的实现依赖于两个关键操作符:typeid和dynamic_cast。

typeid操作符用于获取对象的类型信息。它返回一个std::type_info对象,该对象包含类型的信息。type_info对象的实际内容由编译器生成和维护。

#include <iostream>
#include <typeinfo>

class Base {
   
   
public:
    virtual ~Base() = default;
};

class Derived : public Base {
   
   };

int main() {
   
   
    Base* base = new Derived();
    std::cout << "Type of base: " << typeid(*base).name() << std::endl;
    delete base;
    return 0;
}

在这个例子中,typeid(*base)会返回一个std::type_info对象,表示base指向的实际对象的类型。

dynamic_cast操作符用于进行安全的多态类型转换。它可以将基类指针或引用转换为派生类指针或引用。如果转换成功,返回目标类型的指针,否则返回nullptr(对于指针类型)或抛出std::bad_cast异常(对于引用类型)。

#include <iostream>

class Base {
   
   
public:
    virtual ~Base() = default;
};

class Derived : public Base {
   
   
public:
    void show() {
   
   
        std::cout << "Derived class method called" << std::endl;
    }
};

int main() {
   
   
    Base* base = new Derived();
    Derived* derived = dynamic_cast<Derived*>(base);
    if (derived) {
   
   
        derived->show();
    } else {
   
   
        std::cout << "dynamic_cast failed" << std::endl;
    }
    delete base;
    return 0;
}

在这个例子中,dynamic_cast<Derived*>(base)会检查base是否指向一个Derived对象,如果是,则返回Derived类型的指针,否则返回nullptr。

RTTI的工作流程
  1. 编译时:

    • 编译器为每个包含虚函数的类生成虚函数表,并在虚函数表中添加指向类型信息的指针。
    • 编译器生成type_info对象,用于表示每个类型的信息。
  2. 运行时:

    • typeid操作符通过访问虚函数表中的类型信息指针,获取对象的类型信息。
    • dynamic_cast操作符通过检查虚函数表中的类型信息,确定是否可以进行安全的类型转换。
RTTI的限制
  1. 性能开销:

    • RTTI会增加一些运行时开销,因为它需要在虚函数表中存储类型信息,并在运行时进行检查。
  2. 仅适用于多态类:

    • RTTI依赖于虚函数表,因此只适用于包含虚函数的类(多态类)。对于非多态类,RTTI无法使用。
  3. 可移植性:

    • 不同编译器和平台对RTTI的实现可能有所不同,因此在某些情况下,RTTI可能会有可移植性问题。

0.2 运行时动态类型检查

运行时动态类型检查是在程序运行时进行类型检查,以确保操作数和表达式的类型是有效和兼容的。与静态类型检查不同,动态类型检查是在程序执行过程中进行的,这意味着类型信息在运行时确定。动态类型检查通常用于动态类型语言,如Python、JavaScript和Ruby。以下是运行时动态类型检查的详细解释和其在几种常见语言中的实现方式。

0.2.1 主要特点

  1. 运行时确定类型: 变量和表达式的类型在运行时确定,允许更灵活的编程方式。
  2. 高灵活性: 由于类型信息在运行时可用,可以方便地进行类型转换、动态类型检查和反射。
  3. 潜在的性能开销: 运行时类型检查增加了程序的运行时开销,可能会影响性能。
  4. 延迟错误检测: 类型错误在运行时被捕获,这可能导致运行时错误,增加调试和维护的复杂性。

VIP UE4反射机制的通俗理解【代码生成】 UE4反射机制主要分为以下几个阶段 生成阶段:借助UHT生成对应包含了反射声明的反射代码 收集阶段:借助static自动注册方式,在模块加载的时候,把UCLASS注册,放在array中管理 注册阶段:在模块初始化的时候,将Array中的所有UClass相关的Function和Property注册; 链接阶段:就是反射功能。 第一阶段 在介绍第一阶段前,先介绍两个工具,ubt和uht。UBT是UE4自带的C++工具,用来处理文件依赖,包含。(待理解) UHT则是UE4自带的C++解... 开通可读全文·3.6k 阅读·8 点赞·19 收藏 阅读全文

相关推荐

UE官方教程笔记02-实时渲染基础下

对官方教程视频的笔记

瞎点技能树 5864

UE5反射系统分析(一)generated.h

我们大致分析了中的生成代码,对代码中的不同宏和函数有了一个初步的了解。接下来,我们需要深入到中,看看它们的具体实现,以及在反射系统中的用途,和调用的时机。

异次元的归来 1406

UE5 Lumen与Nanite项目设置指南:从原理到实战避坑

全局光照(GI)与几何渲染是实时图形学的核心挑战,其原理在于模拟光线在场景中的物理传播与复杂模型的实时绘制。Lumen作为动态全局光照系统,通过软件与硬件光线追踪混合技术,实现了实时间接光照与反射,极大提升了场景的真实感。Nanite则革新了几何处理流程,采用虚拟化微多边形和流式传输技术,允许导入电影级高模而不牺牲性能。这两项技术的工程价值在于为开发者提供了影视级画质的实时渲染能力,广泛应用于3A游戏开发、建筑可视化、虚拟制片等高要求场景。本文聚焦于Lumen与Nanite的协同工作流,针对项目初始化、核心

weixin_27070451的博客 295

115.工业相机海康SDK开发指南(阅读)

包含初始化SDK和反初始化SDK接口。(由于看不到函数内部的具体实现,因此以下的解释仅代表个人的理解)

weixin_63779802的博客 5971

实战指南:将MediaPipe封装为Windows DLL,实现C++/C#高效调用

在计算机视觉和多媒体处理领域,跨平台框架为开发者提供了强大的算法模型和计算能力。其核心原理在于通过预训练的机器学习模型和优化的计算图,实现对图像、视频流中特定目标(如人脸、手势、姿态)的实时检测与分析。这项技术的价值在于能够将复杂的AI能力模块化,降低应用开发门槛。在实际工程实践中,为了突破特定语言生态的限制并优化部署流程,开发者常需将核心功能封装成独立的库。例如,将Google的MediaPipe框架封装为Windows动态链接库(DLL),就是一个典型的工程实践。此举能有效解决语言壁垒和部署简化问题,使

weixin_28691741的博客 357

CNC数控机床数据采集,CNC数据采集 设备联网 车间数字化

cnc数据采集 cnc机床数据采集 免受权采集 设备联网

weixin_38175277的博客 2760

MarkDown简介(深度解析MarkDown用法)

欢迎使用Markdown编辑器写博客 本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和图片上传 LaTex数学公式 UML序列图和流程图 离线写博客 导入导出Markdown文件 丰富的快捷键 快捷键 加粗 Ctrl + B 斜体 Ctrl + I...

酷酷的旭 7338

rsyslog交叉编译(armv7、armv8、aarch64、arm32平台通用)

该文档描述了如何交叉编译rsyslog到arm64嵌入式平台。

sinat_33909696的博客 1557

EMC原理-传导(共模、差模)与辐射(近场、远场)详解

本文深入介绍了电磁兼容(EMC)的基本概念,包括EMI和EMS,以及如何处理传导干扰(共模、差模)和辐射干扰(近场、远场)。详细讨论了近场感应、远场辐射的原理,滤波器和屏蔽技术在抑制噪声信号中的作用。此外,探讨了差模和共模干扰的来源、影响及滤除方法,如使用差模电感、电容和共模线圈。最后,提到了穿心电容在滤除高频噪声中的应用。

让你爱上电路设计 3528

【华为OD技术面试手撕真题】3、小行星碰撞 | 手撕真题+思路参考+代码解析(C & C++ & Java & Python & JS)

小行星碰撞,本专栏更新每年华为OD机试的高频手撕代码题,每个题目都会使用五种语言进行解答(C & C++& Java & Python & JS),思路分析都非常详细, 实现最低的时间复杂度和高通过率,每个解题思路超过百字,内含各个编程语言的八股文面试题,欢迎大家订阅学习, 代码可以直接运行使用,全网限时最低价,持续更新

KJ.JK 8157

【华为OD机试真题E卷】514、学生方阵 | 机试真题+思路参考+代码分析(E卷复用)(C++、Java、Py)

【华为OD机试真题E卷】514、学生方阵 | 机试真题+思路参考+代码分析(E卷复用)(C++、Java、Py) 题目描述 学校组织活动,将学生排成一个矩形方阵 请在矩形方阵中找到最大的位置相连的男生数量 这个相连位置在一个直线上,方向可以是水平的,垂直的,成对角线的或者呈反对角线的 注:学生个数不会超过10000

KJ.JK 2480

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

上一篇: 【UE C++】 虚幻引擎C++开发需要掌握的C++和U++的基础知识有哪些?
下一篇: 【UE 网络】专用服务器和多个客户端加入游戏会话的过程,以及GameMode、PlayerController、Pawn的创建流程

双11狂欢大促

盲盒赢 定制羽绒服

开启惊喜盲盒,抽取你的专属好礼

— 惊喜奖品抢先看 —
跨行游戏的GISer
博客等级 码龄7年 1万+粉丝 210原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值