C++实现反射机制(一)

C++ 反射机制(实例讲解) C++反射机制 阅读详情
NET下的很多技术都是基于反射机制来实现的,反射让.NET平台下的语言变得得心应手。最简单的,比如枚举类型,我们我可以很容易的获得一个枚举变量的数值以及其名称字符串。

可是,在C++中,枚举变量本质上和一个整形变量没有区别,我们很难获取一个枚举变量的名称字符串。

其实在C++中,我们可以通过宏来实现类似反射的机制。

接下来,我想总结一下如何在C++中实现一个类似于C#枚举类型的方法。

__VA_ARGS__
使用__VA_ARGS__,我们可以定义带可变参数的宏,举个例子:

#define MY_PRINTF(…) printf(__VA_ARGS__)

这样我们写

MY_PRINTF("hello, %s”, "world");

就等价于

printf("hello, %s”, "world");


 

宏的"##"符号

"##"符号的作用是在可变参数的个数为0时,消除参数前面的逗号:

#define MY_PRINTF(fs, …) printf(fs, ##__VA_ARGS__)

我们这样调用:

MY_PRINTF(“Hello, World”);

等价于

printf(“Hello, World”);

另外"##"符号还能够去掉括号,但是我现在还不是很明白,为什么能够做到这一点:

 

#define ENUM_COTENTS(...) __VA_ARGS__ 
#define ENUM_CONTENT_REMOVE_PARENTHESIS(a) ENUM_COTENTS##a 
#define DEFINE_ENUM(name) enum name { ENUM_CONTENT_REMOVE_PARENTHESIS(ENUM_LIST) }; 
#define ENUM_LIST (Sunday=1,Monday=2) 
DEFINE_ENUM(WeekDay)

宏的"#"符号

"#"符号的作用是“字符化”代码:

#define MY_STRINGLIZED_MACRO(str) #str
int helloWorld = 0;
printf(MY_STRINGLIZED_MACRO(helloWorld)); // output: helloWorld

利用C++宏实现简单的.NET枚举类型

我做了一个简单的用例,最终示例代码如下:

#include "DefineEnum.h" 
#define ENUM_LIST                                   \ 
        ENUM_NAME(Sunday     ENUM_VALUE(10)),       \ 
        ENUM_NAME(Monday     ENUM_VALUE(Sunday+1)),     \ 
        ENUM_NAME(Tuesday    ENUM_VALUE(123)),      \ 
        ENUM_NAME(Wednesday  ENUM_VALUE(10)) ,      \ 
        ENUM_NAME(Thursday   ENUM_VALUE(7)),        \ 
        ENUM_NAME(Friday     ENUM_VALUE(8)),        \ 
        ENUM_NAME(Saturday   ENUM_VALUE(12)) 
  
DEFINE_ENUM(WeekDay); 
  
#include "RegisterEnum.h" 
REGISTER_ENUM(WeekDay); 
  
  
int main() 
{ 
    printf("%s is %d.", EnumHelper<WeekDay>::ToString(Monday), Monday); 
    getchar(); 
    return 0; 
}
DefineEnum.h
#undef ENUM_LIST 
  
#undef ENUM_NAME 
#define ENUM_NAME(...)  __VA_ARGS__ 
  
  
#undef ENUM_VALUE 
#define ENUM_VALUE(val) = val 
  
#define ENUM_COTENTS(...)  __VA_ARGS__ 
  
#define DEFINE_ENUM(name)  enum name { ENUM_COTENTS(ENUM_LIST) };
RegisterEnum.h
#include "ReflectEnum.h" 
  
#undef ENUM_VALUE 
#define ENUM_VALUE(val) 
  
#define REGISTER_ENUM(name)  REFLECT_ENUM(name, ENUM_LIST )
ReflectEnum.h
#ifndef REFLECT_ENUM_INCLUDE_GUARD 
  
#include <string> 
#include <cstring> 
#include <stdexcept> // for runtime_error 
  
#endif 
  
template <typename Enum_T> class EnumHelper 
{ 
public: 
    static const char * ToString(Enum_T e) 
    { 
        for(int i = 0; i < _countof(EnumHelper<Enum_T>::s_allEnums); i++) 
        { 
            if( s_allEnums[i] == e) 
                return s_allEnumNames[i]; 
        } 
        return NULL; 
    } 
  
private: 
    static const char * s_typeName; 
    static Enum_T s_allEnums[]; 
    static char s_singleEnumStr[]; 
    static const char * s_allEnumNames[]; 
  
    static void SplitEnumDefString() 
    { 
        char * p = s_singleEnumStr; 
        while( isspace(*p) ) p++; 
        for(int i = 0; i < _countof(EnumHelper<Enum_T>::s_allEnums); i++) 
        { 
            s_allEnumNames[i] = p; 
            while( *p == '_' || isdigit(*p) || isalpha(*p) ) p++; 
            bool meet_comma = ( *p == ',' ); 
            *p++ = '\0'; 
            if( !meet_comma ) 
            { 
                while( *p && *p != ',') p++; 
                if( *p ) p++; 
            } 
            while( *p && isspace(*p) ) p++; 
        } 
    } 
}; 
  
#define TO_ENUM_ITEM(...)  __VA_ARGS__ 
#define STRINGIZE(...)  #__VA_ARGS__ 
  
#define REFLECT_ENUM(enum_type_name, enum_list)                                                                         \ 
template<> enum_type_name EnumHelper<enum_type_name>::s_allEnums[] =                                                    \ 
{                                                                                                                       \ 
    TO_ENUM_ITEM(enum_list)                                                                                             \ 
};                                                                                                                      \ 
template<> const char* EnumHelper<enum_type_name>::s_allEnumNames[_countof(EnumHelper<enum_type_name>::s_allEnums)];  \ 
template<> char EnumHelper<enum_type_name>::s_singleEnumStr[] = STRINGIZE(enum_list) ;                                  \ 
template<> const char * EnumHelper<enum_type_name>::s_typeName = (EnumHelper<enum_type_name>::SplitEnumDefString(), #enum_type_name);





在鸿蒙系统中实现TS向C++传递包含Map结构的结构体 通过上述方法,我成功地实现了在鸿蒙系统中,TypeScript向C++传递包含Map结构的复杂数据类型。接着,我在C++层实现了对这些方法的调用,通过NAPI(Node.js API for Native Modules)提供的接口,成功地调用了TypeScript中的方法。通过阅读文档和示例代码,我了解到可以通过反射来动态获取类的属性和方法,这对于处理复杂的数据结构非常有用。在项目开发中,我遇到了一个需求:需要将一个包含Map结构的TypeScript类传递给C++层进行处理。 阅读详情

相关推荐

反射机制和类加载机制学习总结

反射机制和类加载机制学习总结 Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。例如,使用它能获得 Java 类中各成员的名称并显示出来。 Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。 JavaBean 是 reflection 的实际应用之一,它能让一些工具可视化的操作软件组件。这些工具通过 reflection 动态的载入并取得 Java 组件(类) 的属性。

C++反射机制的实现

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

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

reflect:C++ 反射框架(为了好玩)

反映 C++ 反射框架(为了好玩) 简单的例子: # include < reflect> int main () { rf:: class_t clss = rf::class_t::for_name ( " hello_t " ); rf:: object_t object = clss. new_instance (); rf:: method_t method = clss. get_method ( " say_hello " ); method. invoke (object); }

C++ 实现反射机制

1. 什么是反射学过 Java 或 C# 的同学应该都知道“反射”机制,很多有名的框架都用到了反射这种特性。这是一种很牛逼的特性,简单的理解就是只根据类的名字就可以获取到该类的实例。有人会说,这不是多此一举吗?直接 new 一个出来不就行了吗?像下面这样:class Person { public: virtual void show() = 0; }class Allen : public

进击的小学生 1万+

i茅台APP加密参数逆向分析:MT-Device-ID与mt-v生成算法

在移动应用安全领域,参数加密是防止API滥用的重要手段。通过对通信协议的逆向分析,可以揭示加密参数的生成原理,这对理解移动应用安全机制具有重要意义。以i茅台APP为例,其关键接口使用了MT-Device-ID和mt-v两个加密参数,前者基于设备硬件信息生成,后者则通过动态签名机制确保请求时效性。这类技术广泛应用于电商、金融等需要高安全性的场景。通过抓包工具和逆向工程手段,可以还原出从设备指纹生成到动态签名的完整技术链条,其中涉及MD5、SHA256等常见哈希算法的应用。掌握这些加密参数的生成逻辑,不仅有助于

weixin_28568819的博客 320

带标签的PHM2009齿轮箱数据集

PHM2009附加数据集—带标签的齿轮箱数据集,可用于测试算法

qq_39379705的博客 4874

c++实现反射机制

一、问题的提出 在c++程序中,如果知道了一个类,然后我们就可以使用类名去访问这个类的 静态公有成员变量 或 静态成员函数: 类名::静态公有成员变量; 类名::静态公有成员函数; 或者我们可以创建这个类的一个对象,然后通过对象去访问公有成员变量 或 公有成员函数: 类名 *pobj = new 类名(); pobj -> ...

akkk1kkka的博客 2490

视频监控设备(NVR、IPC等)如何通过国标GB28181接入到视频监控平台,以及接入过程如何测试视频接入是否成功

GB/T28181标准广泛的应用,视频监控设备通过国标GB28181接入视频监控平台的过程变成程序化、标准化的互联过程,确保了视频监控设备能够在不同系统、不同网络环境下实现远程、跨区域、跨级别的访问和控制。版本有GB28181-2011、2016、2022几个常用版本,威迪斯特的视频监控平台完全支持GB28181的这几个版本,能够实现不同品牌视频监控设备的国标视频接入(国标视频监控接入),或者为国标28181视频接入(国标28181视频监控接入),也为国标281818接入(国标GB/T28181接入。

weixin_70208651的博客 1万+

我所理解的 C++ 反射机制

在实际的项目中,听师兄说项目中用到了 C++ 反射,出于好奇,就查阅相关资料,发现强大的 C++ 本身并不支持反射,反而 Java 支持反射机制。当我得知这个事实时,唯 C++ 马首是瞻的我,心中暗自落泪,悲叹不已。但是,C++ 的拥趸们别难受,强大的 C++ 本身不支持,但却可以让我们手动实现,真的是曲径通幽处,禅房花木深。C++ 是不会辜负我们对它至死不渝的追逐。但是,说到 Java 的反射机制或者 C++ 用到了反射,如果没有真正的在项目中使用过,我们对它会感觉到陌生和不解。

Doublelv 的博客专栏。 3万+

从零搭建AGV避障系统:我用激光雷达+树莓派视觉模块踩过的那些坑

本文分享了基于树莓派与国产激光雷达从零搭建低成本AGV避障系统的实战经验。针对复杂仓库环境,详细剖析了激光雷达数据噪声、视觉模块算力瓶颈、IMU漂移等核心挑战,并提供了多传感器融合、软件架构设计与避障决策的具体解决方案,为中小型自动化改造项目提供了宝贵参考。

git9versioner的博客 984

Cadence OrCAD Capture CIS元器件管理时ERROR(ORCIS-6454): Temporary part number tracking is turned on报错的解决方法

使用Part manager对工程的元器件进行批量管理时,出现如下图所示的ERROR(ORCIS-6454): Temporary part number tracking is turned on报错其解决方法如下。

fydar的博客 3503

C++反射机制:可变参数模板实现C++反射

1. 概要   本文描述一个通过C++可变参数模板实现C++反射机制的方法。该方法非常实用,在Nebula高性能网络框架中大量应用,实现了非常强大的动态加载动态创建功能。   C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数、任意类型的参数。关于可变参数模板的原理和应用不是本文重点,不过通...

北海知己 539

广东省低应变题库

11.按《建筑地基基础检测规范》DBJ/T15-60-2019的规定,采用低应变法对混凝土预制桩进行检测时,地基基础设计等级为甲级的桩基工程抽检桩数不应少于总桩数的30%,其余桩基工程抽检桩数不应少于总桩数的20%,且不得少于10根;16.按《建筑地基基础检测规范》DBJ/T15-60-2019的规定,当对某桩的桩身完整性判定为III类时,可认为该桩不满足验收条件,不用进一步确定该桩桩身缺陷对桩身结构承载力的影响程度。2.地基基础检测所用计量器具均应在检定(校准、验证)的有效期内,性能符合相关技术要求。

ZShy001238的博客 319

C++反射机制实现:结合模板类的实现

背景 最近在实现基础的状态机逻辑,考虑到需要工厂来创建一个指定的状态机,而且调用要简单且可扩展,就想到了反射机制。 以前学习了文章: https://blog.csdn.net/Scythe666/article/details/51718864 给的思路是通过定义回调函数指针类型的方法来实现的,也就是说反射出的对象需要显式地实现实例类创建的回调函数,然后在全局注册进去,虽然步骤已经很简单了,而且一个宏就搞定注册了。 不过我想要在扩展一个需反射对象时,对外暴露的“注册行为”更少,尽量减少一个对象实现时需

Being__的博客 820

Mediatek NeuroPilot Yolov8量化

【代码】Mediatek NeuroPilot Yolov8模型转化。

sdrgtywretyeruet的专栏 346

如何在 Ubuntu 22.04 上安装和配置 VNC 服务器?

VNC(Virtual Network Computing)是一种图形桌面共享系统,通过网络允许用户控制另一台计算机的桌面环境。无论你是系统管理员还是开发人员,VNC 都可以在远程访问桌面环境时提供极大的便利。在安装和配置 VNC 服务器之前,我们需要确保系统是最新的,并安装一些基本工具。这些命令将更新你的软件包列表并升级所有已安装的软件包,以确保你拥有最新的安全修复和功能更新。

网络技术联盟站 4003

C++实现反射

<br />      最近作项目,使用C++.之前.Net和Java用的比较多一点.习惯了使用.Net(C#  or VB.Net or VC.Net)和Java提供的一些特性,到C++里面却没有了.我承认C++确实很强大,但用起来还是那么别扭,觉得C++就是没.Net和Java方便,缺少反射等这种很实用的技术的实现.<br />    我现在做的这个项目是用C++实现,通过类名称字符串就能够创建该类对象的实例.以下是代码实现,可能还需要加工以下,不过解释实现原理倒是可以的.<br />    #incl

shuaiD的专栏 579

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

【C++】Reflection的学习笔记

这个功能目前来说(截止至2023.03.21),这个功能只能用。C++20/23提供的反射支持还不足以完成这样一个功能。“已知函数名称获得函数调用”

墨门 237

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

C++反射

1. 我所理解的C++反射机制 参考:https://blog.csdn.net/K346K346/article/details/51698184 2. c++ 实现反射类 参考:http://www.cnblogs.com/feixue/p/cplusplus_reflector.html 3. C和C++的面向对象专题——C++也能反射 参考:https://blog.csdn.n...

xcw_1987的博客 214

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

map实现c++中的反射(粗略)

看了c#中的反射机制,感觉这个真的好方便啊,然后也想在c++里面实现一个这样的功能,于是在网上看到别人的方法,就是用map来存放类名(字符串)和函数指针,在使用的时候直接用这个字符串来找这个函数指针,执行这个函数。   俗话说,心动不如行动,于是我便将之前简单工厂模式的那个例子拿过来修改,将原来的switch判断符号来实例化算法类更改,使用map将‘+’、‘-’、‘*’、‘/’与具体的算法生产函

hjf161105的博客 903

编译器指令#pragma section的使用

pragma section() 指令的使用

yuanshenqiang的博客 7581

设计模式之反射与配置文件

为了满足“开闭原则”,大部分设计模式都引入了抽象层,如工厂方法模式、抽象工厂模式、适配器模式、桥接模式、命令模式、策略模式等等。客户端代码针对抽象层编程,而在程序运行的时候再指定其子类,根据“里氏代换原则”和面向对象的多态性,子类对象在运行时将覆盖父类对象。如果需要对系统进行扩展或修改,只需修改子类类名即可。在具体实现时,通过引入配置文件可以使得用户在不修改任何客户端代码的前提下增加或替换子类,其

刘伟技术博客 1万+
上一篇: MsgWaitForMultipleObjects 后遗症 与解决办法
下一篇: 计算机视觉方面的代码
雪岢奇
博客等级 码龄17年 310粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值