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

C++根据类名创造不同的类对象(反射) 初衷 最近在写一个SDK,想实现一个管理类,通过传入不同的类名字符串,来实现动态创建不同类。 在Java等一些语音中,实现了一个机制:反射,个人理解可以通过字符串去创建对象,比如: std::string a = "testBase"; //反射即可以通过字符串变量‘a’,来达到创建类”testBase“的目的 这里折中了一下,不通过传入类名来达到创建类对象,而是通过回调函数的名字来达到创建类的目的。 C++实现 函数指针 typedef void* (*funcp)(); 定义一个基类,所有的动态类对 阅读详情

一、具体情况

在前面的文章“名称反射创建对象的一种实现”发布后,有同学问为什么在实例中既给了模板的名称,又给了字符串名称,这还有什么意义呢?这个问题非常好,当时一时偷懒,没有把事情说清楚,这篇文章算是对提问同学的一个回答。
其实很简单,如果把实现的类名和声明的类型换成不同的类,同时这个需要反射的类必须继承前面提到的ClassInstance,再在给定的类(即Worker)中实现一个创建,那么整个反射的过程就符合了一般反射的习惯。

二、补充例程

基于上面的分析,看下面的代码分析即可明白:

......

//测试类
class Worker {
public:
    Worker() {}
    Worker(int a, int b) : a_(a), b_(b) {}

public:
    void display() { std::cout << "-this is Worker display function!--:" << a_ + b_ << std::endl; }

private:
    int a_ = 0;
    int b_ = 0;
};

class Worker1 {
public:
    Worker1() {}
    Worker1(int a) {}

public:
    void display1() { std::cout << "--this is worker1 display1 function--" << std::endl; }
};

int main() {
    //重点看这里的声明和后面的获取,即下面的两行代码
    ClassInstance<Worker, int, int> dc;
    auto* pp = InstanceFactory<Worker, int, int>::Instance()->CreateInstance("Worker", 1, 2);

    pp->display();

    return 0;
}

上面就上次发的代码的问题提出部分,这次完善一下代码:

//实例模板
template <typename T, typename... Args>
class ClassInstance {
public:
    struct RegContain {
        RegContain() {
            char* sName = nullptr;
            std::string className;

            //注意:这是Linux平台,其它平台需要处理相关类名
           // sName = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
            sName = name;
            if (nullptr != sName) {
                //className = sName;
                //free(sName);
            }

             className = name;
            InstanceFactory<T, Args...>::Instance()->RegClass(className, CreateObject);
        }
        inline void done() const {};
    };

public:

    ClassInstance() {
        //this->InstanceFromName();
        reg_.done(); // 确保调用前模板实例化,请参看前面的模板延迟加载
    }
    ~ClassInstance() {};
public:
    // 变参创建实例
    static T* CreateObject(Args &&...args) {
        T* pIns = nullptr;
        try {
            pIns = new T(std::forward<Args>(args)...);
        }
        catch (...) {
            return nullptr;
        }
        return pIns;
    }

private:
    static RegContain reg_;
};

template <typename T, typename... Args>
typename ClassInstance<T, Args...>::RegContain ClassInstance<T, Args...>::reg_;
//测试类
class Worker :public ClassInstance<Worker,int,int> {
public:
    Worker() {}
    Worker(int a, int b) : a_(a), b_(b) {}

public:

    void display() { std::cout << "-this is Worker display function!--:" << a_ + b_ << std::endl; }

private:
    int a_ = 0;
    int b_ = 0;
};
class ObjIns {
public:
    template<typename ...Targs>
    Worker* GetObj(const std::string& name, Targs&&... args)
    {
        Worker* p = InstanceFactory<Worker,Targs...>::Instance()->CreateInstance(name, std::forward<Targs>(args)...);
        return p;
    }
};
int main() {
    ObjIns o;
    auto *pp = o.GetObj("Worker",3,6);

    pp->display();
}

这里的代码主要修改了两处,一处是将实例代码的生成InstanceFactory从函数转到了内部类,确保模板在调用函数前的实例化(当然也可以使用其它的方式);另外一个就是将实例的应用封装了一层,即原来的Worker不直接暴露,而是通过一个对象类ObjIns来动态创建,这样就更符合开发者对反射使用的要求。
有的同学可能会问,这个还是有问题啊,每次都得创建一个新类的构建函数来实现啊,同学可以想一想,是不是在某种场景下,可以使用继承?或者干脆把功能从Worker中单独提取出去?再使用继承!自己可以试试,网上很多的代码其实也是这个思路。

三、总结

这个怪偷懒的精神做祟,说明一下就好了。这也说明,对细节的说明一定要清晰严谨,不能想当然的别人也会这么理解。沟通的成本,就是这样产生的。谢谢热心同学“ω劉εз珩”的指出,非常感谢,共同进步。

C++反射动态创建所需类的实例 使用单例,工厂,函数指针实现的反射,减少了分支语句,次方法可以动态创建类实例,减少了工厂类里面的分支语句(工厂类完成后基本不需要修改,就可以随意创建想要的类的实例)。 立即下载

相关推荐

从零搭建ROS机械臂仿真环境:Ubuntu 20.04+Noetic下配置睿尔曼RM65的完整流程

本文详细介绍了在Ubuntu 20.04系统中,基于ROS Noetic搭建睿尔曼RM65机械臂的完整仿真环境。从环境准备、工作空间创建到MoveIt!配置与Gazebo仿真环境集成,提供了完整的流程和优化建议,帮助开发者高效实现机械臂仿真与调试。

v6b7n8m9q0的博客 933

c++如何实现类名创建类对象(反射)

c++开发过程中使用工厂模式创建各种类对象的时候可能需要写一堆的’if-else’函数来根据传入的参数类型创建不同的类对象;步骤: 1> 创建一个单例工厂类, 类中维护一个类名和创建对应类的回调函数的映射关系(map) 2> 需要创建的时候根据传入的类名参数查找对应的回调函数来创建类。这样的效果. 其实就是JAVA中的反射机制的体现, 实际c++本身是不支持的, 但是可以通过曲线救国的方式来实现.核心: 通过回调函数来实现创建.

SuperYang_的博客 1056

对西安交大轴承数据集XJTU-SY_Bearing_Datasets进行读取和处理:

故障诊断,对西安交大轴承数据集XJTU-SY_Bearing_Datasets进行读取和处理

qq_44757503的博客 6058

C++类对象反射机制的实现(动态创建类对像并给类的字段赋值)

class_name::GetFieldArray() 获得字段信息结构数组地址,一定要加上括号才能获得字段数据,类的字段信息还是没有添加数据,这就要在前面声明宏中创建一个运行时类对象来添加。不能添加到最后,因为最后是一个不全的函数,要和结束宏组成一个完整的函数的,1.2.把类名称,类的字符名称,类的字段数据类型都要注册到对应的链表中。类的运行时信息也有了,但是如何在程序运行时往这类中添加相应的数据呢,如从数据库中读取数据,并自动添加数据到对象的相应字段中,Get_Field_Values();

qq_31178679的博客 528

【嵌入式Linux】EC20模块多运营商自适应PPP拨号实战:从IMSI识别到网络配置

本文详细介绍了在嵌入式Linux系统中,如何基于EC20 4G模块实现多运营商自适应PPP拨号。通过解析SIM卡的IMSI识别运营商,并动态配置对应的APN和拨号参数,结合AT指令交互与健壮的pppd脚本,解决了设备跨地域部署时的网络自动连接问题,提升了物联网设备的部署效率和稳定性。

fox11的博客 897

保姆级教程:用SSC Tool 5.13为先楫HPM6E00EVK生成8轴EtherCAT从站代码(含XML配置详解)

本文详细介绍了如何使用SSC Tool 5.13为先楫HPM6E00EVK开发板配置8轴EtherCAT从站,包括XML文件深度配置、代码生成与工程整合、烧录与调试技巧。教程涵盖从环境准备到性能优化的全流程,帮助开发者快速实现符合CIA402标准的8轴控制。

weixin_30352645的博客 254

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

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

fpcc的专栏 8001

科研党福音:如何用Zotero+Paper Agent打造你的AI论文速递系统(附详细配置教程)

本文为科研工作者提供了一套利用Zotero和开源工具Paper Agent构建自动化AI论文速递系统的详细教程。该系统能基于用户在Zotero中的文献库智能学习研究兴趣,每日自动从arXiv等平台筛选、下载并深度解读最相关的前沿论文,生成个性化日报,实现从被动接收到主动精准获取的知识工作流重塑。

kite3的博客 510

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

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

fpcc的专栏 820

从HCI层浅析LE Audio通话建立流程

本文分析了BLE AUDIO通话协议建立的全过程。当手机来电时,系统会通过CCP EATT链路通知耳机准备通话,并断开原有音乐CIS连接。随后建立通话专用的CIG组,其参数设置(如MAX SDU SIZE=80、RTN=2)与音乐场景明显不同,更注重通话的实时性。文中详细描述了设置ISO数据路径、启用ASE、建立CIS连接等关键步骤,特别指出通话采用Conversational音频上下文类型。最后解析了ISO数据包参数含义,展示了10ms周期、32kHz采样率等通话特性参数。整个过程体现了BLE AUDIO

十多年蓝牙协议软件开发,擅长蓝牙协议分析 1860

Python APP反爬实战:Frida+Charles抓包,破解签名校验

Charles抓包定位参数 → jadx-gui反编译找函数 → Frida Hook拿密钥/规则 → Python还原签名算法;Frida的核心价值:Hook住APP的加密函数,拿到“输入(密钥/参数)+输出(签名)”,无需懂复杂的逆向底层;严格对齐APP的参数排序、拼接规则、加密算法,差一点都会验证失败。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1535

C++实现简单的反射——根据字符串创建类对象

最近项目需求中需要一个关键功能——根据字符串创建了类对象。由于C++没有类似Java、C#这类动态语言中的反射机制,所以在C++程序中一般用if…else…或者switch来将字符串或者枚举值与类对象的创建方法来进行对应的映射。这里如果我们实现一个简单的反射机制,可以根据字符串创建了类对象就可以简化这个过程,而且无论对修改还是扩展都会更加方便。 理想的使用方式就是我们需要这个功能的类统一继...

吴尼玛cs 2557

标准测试测试数据STDF学习笔记

本文介绍了STDF(Standard Test Data Format)文件的结构与解析方法。首先详细说明了STDF记录的组成,包括记录头类型(REC_TYP和REC_SUB)、数据类型定义、时间日期格式以及无效数据标识。重点分析了25种主要记录类型的功能、数据内容和出现位置,如FAR、MIR、MRR等关键记录。然后介绍了基于pystdf开源工具的解析方法,包括自带脚本的使用和自编程解析流程,通过事件驱动机制处理数据流。特别指出测试数据是按照PIR→PTR/MPR/FTR→PRR的循环模式组织。文章为ATE

歌颂苦难的行为是无耻的; 1513

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

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

fpcc的专栏 1532

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

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

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

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

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

fpcc的专栏 2742

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

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

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

fpcc的专栏 621

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C++实现反射(根据类名动态创建对象)

和网上大多数实现一样,本文也采用工厂方法来实现对象的动态创建,唯一不同的在于,本文的实现优化了类的注册,使用起来更为简单。废话不多说,直接上代码(这也没什么可说的,看代码更加直观)。 DynamicFactory.h文件,需要支持动态创建对象的地方,包含此文件,然后继承DynamicCreate即可。 #ifndef __DYNAMIC_FACTORY_H__ #define __DYNAMI

heyuhang112的专栏 1万+

c++ 反射机制: 用类名作变量,动态创建对象

什么是反射 从创建对象的角度上来看,狭义的说,比如有个 class A ,你能直接 new A() 来创建 对象。但是如果想根据字符串 “A” 来创建 class A 的对象,比如 使用 new “A” 的形式来创建 对象,甚至 “A” 是个变量。 str = “A” , new str. 这种把 class 作为变量,又能在运行时创建对象的机制,就叫做反射。 大部分的高级编程语言,先天是...

杂七杂八 5686

C++反射通过字符串创建类对象

1、前言 之前一直想通过配置文件如xml,配置一个类名,通过这个类名创建对象,通过基类指针来指向派生类,管理一系列这样对象,继承,这样的可以不修改管理咧,直接添加或修改配置文件来动态创建管理类,非常方便。由于C++没有反射机制,但是可以实现。 2、实现 (1)为需要反射的类中定义一个创建该类对象的一个回调函数; (2)设计一个工厂类,类中有一个std::map,用于保存类名和创建...

阿Sir问道 1725

C++性能测试工具——gperftools的安装

一、软件安装说明 gperftools的安装有再从种方式,一种是源码方式,一种是直接安装模式。这里源码安装模式,原因是使用直接安装模式比较简单。安装此软件需要先安装libunwind这个软件,所以这里需要通过源码方式安装libunwind,否则会报一个警告:“configure: WARNING: No frame pointers and no libunwind. Using experimental backtrace capturing via libgcc.Expect crashy cpu pr

fpcc的专栏 1万+

cmake对编译器版本和库依赖的问题

cmake对编译器版本和库依赖的问题 一、介绍 最近在编译Wasm的几个相关工具时,其使用的是cmake工具,一般来说,开源的软件的编译文档会写的相当清楚,而且开源软件为了让客户体验方便,一般编译的步骤和依赖的相关工具和库,都会尽量整合到一起,防止因为无谓的原因导致编译问题影响软件的整体下载应用。 在编译相关的工具过程中,确实发现很多都基本可以做到两三到命令即可完成编译,也不需要下载过多的依赖。但...

fpcc的专栏 1万+

多核和多CPU编程——并行计算的加速比

一、并行计算的衡量 并行计算和串行计算到底哪个好,或者说并行计算中哪个优哪个劣?这需要有一些衡量的标准: 通过上述的参数的对比,可以在整体上有一个性能的参考。 二、加速比(Speedup) 加速比就是指并行计算比传统的串行执行速度提高了多少倍。即: 加速比(Sn)=单处理器最优算法串行时间/多核并行计算时间 它涉及到两个定律: 1、Amdahl定律 Gene Amdahl于1967年提出了这个定律,用于在并行计算相对于最优串行算法在性能上提升的理论上的最大值: 上面的主要说明如下: n: 并行系统中处理

fpcc的专栏 1万+

C++性能测试工具gprof和gperftools基础

一、程序的性能及测试 软件的性能指的是软件所能满足的性能指标,主要包括压力测试指标和负载测试指标。软件的性能测试是通过模拟实际生产的业务压力和具体环境组合,来测试系统的性能是否达到软件设计的性能指标。在c++的应用程序里,天然的要求就是高性能,这也是对c++性能测试的一个痛点。目前常见的大型软件,用c\c++实现的非常多,比如数据中的MySql,内存型数据库Redis,微信和QQ,损伤系统等等。 掌握常见的c++性能测试工具,对于c\c++开发人员来说,是一项必备的技能。它能够帮助开发者,快速发现大型应用程

fpcc的专栏 1万+

C++性能测试工具gprof安装和应用

一、gprof的安装和说明 在前面谈过了gperftools的安装,今天来看一下gprof的安装。虽然说gperftools安装比较复杂,但是gprof就好说了,因为只要你的机器上装有GCC,那么自然就带了这个软件。如果没有的话,就按照以下的方法安装一下新的gcc即可。不过一般来说,系统都会自带相对最新的gcc,这个不用太担心。 https://blog.youkuaiyun.com/fpcc/article/details/99698783?ops_request_misc=%257B%2522request%255

fpcc的专栏 9950

c++性能测试工具——gperftools的应用

一、应用场景 性能测试的应用场景除了大规模计算、寻找瓶颈之外,其实对于不停服的服务端程序(包括Web服务和CS服务端等),更具有实战意义。在此类的实际场景中,经常存在以下几个问题: 1、服务端调优,需要找到性能瓶颈,而往往这种瓶颈并不是随时出现,而是随机出现的。 2、问题异常的发现,比如偶尔会有突然的报警或者CPU内存等异常升高。 3、多方比较,与同类型或者友商类似软件的性能比较分析 4、设计验证,也就是开发架构时的设想与实际上线后有何差别,差别有多大。 这些都需要一些量化指标,而这些量化指标,就需要通过测

fpcc的专栏 9209
上一篇: 跟我学C++中级篇——零长度数组
下一篇: 一步一步写线程之十一线程池应用内存池
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、付费专栏及课程。

余额充值