跟我学c++高级篇——反射的基本实现方式

C++ 反射机制(实例讲解) C++反射机制 阅读详情
AI摘要

文章介绍了C++中如何通过宏、模板和元编程等技术实现反射功能,虽然C++原生不支持反射,但随着标准的更新,反射技术逐渐得到支持。文中列举了获取类名、参数数量、类型和地址的方法,并提及模板和元编程在反射中的应用。

一、c++中的反射基本实现

综合反射在各种高级语言中的应用以及前面分析过的反射的原理,就可以明白,一种概念或者说技术在某种语言中是否拥有,更准确的其实是说是否原生拥有。毕竟,没有可以通过某种技术或者手段模拟出来,理论上说,只要达到最后的效果相同,就可以认为支持这项技术。反射亦是如此!
c++原生可以说基本是不支持反射的,但是通过一些技术手段可以实现,特别是随着c++标准的迭代,包括反射的一些技术增加到了标准内,这就意味着,c++原生支持反射的可能性会越来越大,但能支持到何种程度,就是另外一种问题了,做标准可不比开发程序,要严谨很多,不然也不会有不少的技术被标准委员会反复推延。

二、反射实现的方法

在c++中,基本的静态反射,可以通过宏和模板来实现,当然二者结合也可以实现。这里还是强调一下,单纯的为了反射的目的的而模拟实现反射效果的暂时不在此讨论之列。在宏和模板实现反射的机制下,可能会利用到萃取和特化。特别是前面提到的一些SFINA和元编程等中的技术(变参模板和变参宏等)。
正如前面分析提到,要想实现反射,首先知道类的信息,这些信息包括大小,名称,变量数量、地址,函数的地址等等。换句话说,需要通过宏和模板等技术只要能得到这些信息,就基本可以实现反射了。不过,在实现的过程中,如何更简单高效的完成工作和达到目的,这就需要八仙过海的本事了。

三、例程

上面提到了,要想实现反射,必须能得名称、属性(类内部变量定义)、地址等,那么就需要先处理最常见的,拿到名称和处理数量

1、得到名称
这个比较简单毕竟类的名称都是可以各种方法得到的,而且在反射的过程中一般也会给出类的名称。而且用宏来处理这种事情极其简单,字符串的替换即可。当然,c++中也为基础的类型提供了typeid可以得到名称。

2、得到数量
这个可以用模板和宏,下面是宏的方式:

//注意:VC编译器把宏可变参当成一个整体进行预处理展开,可能结果有问题,可启用/Zc:preprocessor编译选项,或引入ZH_EXPAND(...) VA_ARGS 展开,建议在Gcc下展开。
#define GET_NTH_ARG(  _1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9,  _10, _11, _12, _13, _14, _15, _16, n, ...) n
#define GET_ARG_COUNT(...) GET_NTH_ARG (__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9,  8,  7,  6,  5,  4,  3,  2,  1)
int main()
{
    GET_ARG_COUNT(a,b,3,d);
}

这个代码的参数可以自己按照需要进行扩展,写成1~N,当然N不可能太大,毕竟实际情况有十个参数的都是多的了。不过这个不支持0个的参数的。
下面是模板的方式:

#define TEM_GET_PARAM_SIZE_BY_CONSTEXPR (...) TempGetParmCons(__VA_ARGS__)
#define TEM_GET_PARAM_SIZE_BY_SIZEOF(...) (sizeof(TemGetParmBySize)(__VA_ARGS__))/sizeof(char) -1
#define TEM_GET_TYPE_SIZE(...) TemGetTypeSize<__VA_ARGS__>::value

template<typename ...T>
constexpr size_t TempGetParmCons(T ...params)
{
    return sizeof ... (T);
}
template<typename ...T>
auto TemGetParmBySize(T&& ...param)->char(&)[sizeof ...(T) + 1];

template<typename ...T>
struct TemGetTypeSize
{
    static constexpr size_t value = sizeof ... (T);
};

这个技术就更简单了,只是简单的使用了sizeof…的各种情况。

3、得到类型和地址
通过宏还可以得到很多的东西,比如利用#,##进行字符串的处理和连接。还可以以去除、增加小括号(也可以同时处理括号内容),这样就可以在宏反射过程中得到具体的类型和变量以及它们的名称。

#define TYPE_NAME_ALLDEL(...)
#define TYPE_NAME_DELP(...) __VA_ARGS__
#define TYPE_NAME_GET(n) TYPE_NAME_DELP n

#define CLASSMEM_OFFSET_TYPE(m,...)(reinterpret_cast<size_t>(&reinterpret_cast<char const volatile&>((((__VA_ARGS__*)0)->m))))

4、模板处理表达式展开和元数据处理
在前面的分析提到过,可以用折叠表达式来完成自动的展开,而这种展开就可以通过模板来实现对反射过程中的序列化:

template<typename T>
struct Serializer
{
    using mSequence = std::make_index_sequence<T::mSize>;

    template<size_t ...M>
    static void WriteDataStream(std::index_sequence<M...>, const T& cv)
    {
        (T::template SeqMeta<M>::WriteData(cv), ...);
    }

    static void WriteData(const  T& cv)
    {
          WriteDataStream(mSequence(),cv);
    }
};

当然,萃取和SFINAE等技术都可以用到其中,就看对开发的需求了。另外一些新的c++标准中的技术也可以应用,比如Concepts等都可以很好解决一些问题。当然,typeid,sizeof…,decltype等就更不用提了。
5、模板技术和元编程
元编程就不用说了,模板技术也可以广泛的应用到反射中来,比如模板的偏特化等等,这些在前面都有不少的例子,这是就不再展开了。

本来想搞一个简单的应用做个例子,发现还真是有点难度(几十行代码真不好写出来)。还是后面再专门写一篇相关的文章为好。反射确实是比较不好写的容易懂,毕竟当初光宏编程就惹得一众声讨,更别说再加模板和元编程,这个得慢慢来。另外,反射本身在新的c++标准中可能会不断的完善,分析讲解的一些技术可能过几年就不会在反射中应用了,这个还是需要看标准的发展和应用的普及程度。

四、总结

太极生两仪,两仪有四象,四象生八卦。正如道家所说一生二,二生三,三生万物。学习也要从简单抓起,然后反复不停的在此基础上锤练,不断的向上发展,让整个体系愈发的完整并且向着新的未知不断的探索。对个人来说,技术的精湛莫不如是。对技术本身来说,更是如此。
要站在巨人的肩膀上,不断的向前看,看向更高。

C++实现反射(Reflection) C++实现Reflection最近1年多,我一直在琢磨和大量使用cli来开发游戏项目,.net系统的反射系统给我的开发设计思路,带来了很大的冲击。反射真的可以从根本上,让设计思路相对传统开发模式有很大的改变。但是反射通常都提供在类似java等动态语言上,后来ms在.net平台上推出了一个很强大完善的反射机制,我最近1年多的项目都是大量使用他,为我的项目开发,做出了很多有意思的东西。但是我的vi 阅读详情

相关推荐

LM Studio中文版零基础入门:从安装到模型下载的保姆级教程(附国内镜像源配置)

本文提供LM Studio中文版的零基础入门教程,涵盖从软件安装、中文界面切换到国内镜像源配置的全流程。特别针对模型下载速度慢的问题,详细介绍了如何通过修改配置文件使用国内镜像站,并推荐适合新手的入门模型及硬件配置建议,帮助用户快速上手本地大模型运行。

pz890123456的博客 2582

跟我学c++高级篇——反射

其实反射也可以放到模板元编程中来进行分析,但是为了更好的讲解一些c++的高级特性,还是把它分离了出来。c++的许多高级的特性,在国内的大多数应用场景上,其实是应用不到的。原因是,这些高级特性大多是在基础库支持或者基础软件上才用的。而这恰恰是国内的软肋。知已知彼,百战不殆。看到有什么不足,才能更好的补齐它。共同努力!

fpcc的专栏 8001

Waymo数据集里的隐藏彩蛋:5个激光雷达数据融合实战(附Python代码)

本文深入解析Waymo数据集中5个激光雷达的数据融合技术,提供Python实战代码,帮助开发者掌握多传感器协同工作的关键方法。通过时间同步、坐标转换和运动补偿等技术,实现高精度3D场景重建,提升自动驾驶系统的环境感知能力。

weixin_30399821的博客 79

C++反射机制的实现

1.什么是反射 首先看一个问题:如何通过类的名称字符串来生成类的对象,比如有一个类Class A,那么如何通过类名称字符串“Class A”来创建类的对象呢? C++本身是不支持通过类名称字符串"Classxx"来生成对象的,也就是说我们可以使用ClassXX* object =new ClassXX;来生成对象,但是不能通过ClassXX* object=new "ClassXX";来生成对象。 要想解决这个问题就要用到反射,我们先看下维基百科的定义:反射是指计算机程序在运行时可以访问、检测和修..

C/C++、嵌入式开发、深度学习算法、模型部署与推理优化 1万+

OV5640调试大坑,关于binning、RES分辨率与EV曝光

OV5640在使用binning模式时,必须考虑使用场景,分辨率下降叠加动态范围压缩,会使目标对象细节在高光环境下大量丢失,2x2的binning模式,分辨率会远低于感光面积的1/4。

chongyun_的专栏 1822

SIMPLIS仿真软件2.2-SIMPLIS快速入门2

SIMPLIS仿真软件2.2-SIMPLIS快速入门2导读 导读 本文承接上一篇文章。开始介绍SIMPLIS仿真部分。正如上一篇所讲的快速入门的定位,该文对SIMPLIS的三种分析模式不会很深入的讲解,只会记录下一些重要的设置和操作。对于SIMPLIS的三种分析模式的详细讲解,后面会专门撰写。如果读者还没有搭建上一篇文章中讲述的电路,那你可以点击这个链接免费下载所需的电路SIMPLIS_tutorial_buck_converter ,然后在这个电路的基础上继续进行以下操作。 ...

qq_44677482的博客 2万+

跟我学c++高级篇——反射的基本原理

对反射在c++中的应用,大多数开发者可以忽略它。对国内来说更是如此,有兴趣可以搞一搞,如果没有兴趣的话,大可以束之高阁,等有需要的时候儿再拿起来现炒现卖,单纯在上层应用,肯定不会有多复杂。不用在过于担心会不会被标准扔得远远的。

fpcc的专栏 2742

AI人工智能与TensorFlow的教育科技应用

随着科技的飞速发展,AI人工智能在各个领域都展现出了巨大的潜力,教育领域也不例外。本文章的目的在于深入探讨AI人工智能与TensorFlow在教育科技中的具体应用,包括智能教学系统的开发、学生学习情况的评估与预测等方面。范围涵盖了从基础概念到实际项目应用的各个层面,旨在为教育科技工作者和相关研究者提供全面且深入的技术指导。本文将首先介绍AI人工智能和TensorFlow的核心概念及其联系,让读者对相关技术有基本的了解。接着详细讲解核心算法原理和具体操作步骤,并结合数学模型和公式进行深入分析。

AI智能探索者的博客 1693

跟我学c++高级篇——类反射

反射对c++是不是一种鸡肋,这个还真不好说。不过有一句话可以引入进来,“发展是硬道理”,只要是不断的发展,就会有机会。而停滞不前的空谈理论,一定是没有前途的。至于以后反射在c++后续标准里会成为什么样子,大家拭目以待即可。

fpcc的专栏 1580

通达信量化打板选股指标公式源码副图

X_2:=3*LOW;X_13:=4;X_14:=3;X_15:=2;X_16:=1;

gpzb7的博客 4480

基于A*算法的二维栅格地图路径规划与避障MATLAB仿真

本文将介绍如何使用MATLAB编写基于A*算法的二维栅格地图路径规划与避障的仿真程序。我们可以使用二维数组表示地图,其中每个元素表示一个栅格的状态,例如1表示障碍物,0表示可行走区域。接下来,我们需要定义A*算法的节点类。G值表示从起始节点到当前节点的代价,H值是启发式函数估计的从当前节点到目标节点的代价。算法,我们可以有效地找到起始点到目标点的最短路径,并在仿真中进行可视化展示。算法的基本思路是从起始节点开始,按照一定的启发式函数选择下一个节点,直到找到目标节点或者遍历完所有可行走区域。

ByteWhizX的博客 1272

跟我学c++高级篇——常见的反射框架

在前面基本已经把基础的反射分析了一遍,通过这些学习,已经可以知道C++中反射的特点在哪里。他山之石,可以攻玉,在本篇就结合在网上的一些开源的反射框架来对反射加深一下印象。目前开源的c++反射框架中,各种类型的都有,复杂的简单的,针对具体类型的和通用的。一般来说,大厂和国外的开源写得相对要好一些,但不是说个人写的就不好,个人一般很多都是自己针对自己的具体场景,所以可能通用性差一些。

fpcc的专栏 2264

《计算机视觉:从入门到精通》技术手册 第1章 计算机视觉概述与历史演进

视觉感知与机器视觉在工程实践中常被混用,但二者存在本质差异。视觉感知强调对光学信号的语义理解与场景解释,核心在于从二维投影重建三维世界的物理与语义属性。该领域关注遮挡处理、光照变化、材质反射等复杂因素的建模,其目标是实现类似人类视觉系统的场景理解能力。机器视觉则侧重于工业场景中的精密测量与控制,通常基于结构化光源、已知几何约束与标定参数,执行边缘检测、尺寸测量、位置定位等任务。前者面向开放环境的通用理解,后者面向受控环境的精确执行。

u012133341的博客 267

跟我学c++高级篇——C++26反射预览

看了c++26中的提案,可以发现其实很多现在的反射框架的轮子基本都可以废弃了。不过,能把反射最终支持,估计得2028年左右了,时间还有的是。喜欢造轮子的同学可以继续造,反正在造轮子的过程中,可以更好的学习反射的原理和实践,同样能更好的理解新标准中的反射。这样,在未来的应用中,也会更加轻松的引入标准库内的反射。在后面反射实现分析讲解中,基本也会沿着大致相同的路线进行。

fpcc的专栏 4057

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

跟我学c++高级篇——静态反射实现之一

反射写起来非常头痛,一个是不知道如何说起更有系统性;另外一个就是哪种反射更有利于实际的应用。所以反射这个系列可能会是一个很长期的总结过程,大家不要着急,一定会把坑慢慢填好。

fpcc的专栏 1832

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

跟我学c++高级篇——基础类型和POD结构体反射

由简入繁,从基本到深入总是需要一个过程,学习反射也是如此。写代码是为了把学习的知识验证一下,同时可以更加深刻的理解知识。开发者们经常遇到这种场景,几行简单的代码,琢磨半天也确定不了什么意思,但是上机一调试,就恍然大悟。这就是侯捷教师的那句话“源码之前,了无秘密”。反射还是有些难度的,所以这个系列会慢慢增加。

fpcc的专栏 1532

跟我学c++高级篇——静态反射实现之二函数接口实现

不断的抽象实现可以保证设计上的依赖于抽象而不依赖于实现,也就使得代码更有普适性。但多层次的抽象导致的结果可能是代码阅读上的困难和维护上不方便。这个就是仁者见仁了,一般来说,对于库等升级比较正式而且不怎么频繁的项目可以尽量抽象,而对于应用层,抽象要适当。不过在现在的环境下,就根据情况自己选择吧。

fpcc的专栏 644

跟我学C++高级篇——名称反射创建对象的一种实现

在后期的文章和实例中,大家会发现,会越来越多的把前面的知识融汇贯通,有可能再加上一些新知识点,就会实现一个比较好的技术点。所有的技术应用,一定是在基础技术上的不断的抽象升华。一种完全全新的,不以前边的技术为基础的技术,几乎很难遇到。或者如此说,即使遇到了,也可以通过老的技术快速的体会到新技术的优缺点。但这有一个前提,思想必须永远是开放包容,与时俱进!

fpcc的专栏 820

跟我学c++高级篇——reflexpr

这一章的实践意义并不大,但实际意义其实是很大的。学习知识最容易的方式不是直接拿过来用,也不是从头一点点的扣出来。学习知识最快捷的方式是把当下的技术搞明白,同时把某些关键技术的来历再理清晰,脉络分明后,学习的效率就会迅速增加。简单是技术普及的前提!

fpcc的专栏 956

跟我学c++高级篇——动态反射之一遍历

这篇内容就有点接近正常理解的反射的意思了,本来这篇想把一个动态表生成的方式也分析了,但是又觉得太长了,还是分到下一篇再一起分享。慢慢来,不要急。

fpcc的专栏 563

跟我学c++高级篇——动态反射之二动态列表

在上文说过,本来这篇是和上一篇打算合在一起,可是又觉得它们有点不同的意思,就拆分了开来。其实说来归去,重点是理解如何进行反射前的准备,把相关的字段名称都准备出来,只是同一个基础的应用,却可以在上层写出不同的反射方法来,这也是c++总被称为难的原因。因为其灵活,不容易掌握,而每个方法又有长处和不同的适应场景,这都需要开发者自己权衡,这就是难的原因。见仁见智,各取所需吧。

fpcc的专栏 418

跟我学C++高级篇—运行时反射的std::type_index

C++通过std::type_index、type_info和typeid提供了轻量级的反射支持。typeid运算符返回type_info对象描述类型信息,type_index则是对其封装以便标准容器使用。主要应用场景包括类型映射、工厂模式、类型擦除等,但需注意哈希冲突、跨平台兼容性和异常处理等问题。示例展示了如何利用type_index构建类型管理系统。虽然C++的反射功能有限,但这些基础RTTI工具仍为开发者提供了类型操作的基本能力。随着标准演进,反射支持有望进一步完善。

fpcc的专栏 697

跟我学c++高级篇——模板元编程之六SFINAE

SFINAE,对于想在模板编程中有更深的想法时,建议还是要认真学习。其实SFINAE更像是模板编程中更进阶的一种用法,虽然它可能在复杂的应用情况有些晦涩难懂,但既然决定想搞c++的模板编程,一些精深的东西还是需要去学习的。特别之于模板的元编程,更是如此。虽然有了concepts,但看以前的代码还是需要懂得这个技术的。

fpcc的专栏 4768

跟我学C++高级篇——名称反射创建对象的一种实现的说明

这个怪偷懒的精神做祟,说明一下就好了。这也说明,对细节的说明一定要清晰严谨,不能想当然的别人也会这么理解。沟通的成本,就是这样产生的。

fpcc的专栏 483

跟我学C++高级篇——获取类型名称的番外小插曲

其实今天分析的这个现象,再次验证了标准是标准,实现是实现这个道理。标准指挥着实现,但实现不一定必须严格按标准来。有些标准未要求到的或者说对实现手段和结果没有要求的,这都是编译器厂商可以自行决定的。包括在实现标准后再在其基础上进行扩展支持的,这都不少见。标准是方向和目标,编译厂商是行动者和实践者,达到目的不一定非得走一条路。

fpcc的专栏 621
上一篇: 跟我学c++中级篇——模板嵌套中的依赖限定
下一篇: C++中两个宏__PRETTY_FUNCTION__和__FUNCSIG__的应用
fpcc
fpcc 新星创作者: C/C++技术领域 新星创作者: C/C++技术领域
博客等级 码龄22年 4038粉丝 1185原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值