添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
坏坏的皮蛋  ·  Error during ...·  8 月前    · 
正直的跑步鞋  ·  David龔_換位思考 - ...·  1 年前    · 
爱搭讪的蚂蚁  ·  使用.net ...·  1 年前    · 

Introduction

本来是想总结一下关于C++反射的知识,但是在查资料的过程中,发现自己认知中的反射不过是真正的反射的很小的一个应用,所以这里修改了自己的标题,以使其具体地反映其功能。

从字符串获取类对象的思路

为了从字符串获取一个类的对象,一个可行的思路是建立 字符串与类的一个映射关系 ,为了方便操作,我们可以把这种映射关系放在一个map结构中: std::map<std::string, ?> 。一种理想化的映射是我们直接从字符串获取类型名称 std::map<std::string, CLASS> string_class ,并在后续通过类型名称来构造对象 string_class[str] object 。但是在C++对反射尚没有很好的支持的时候,这种方法貌似也很少有人去尝试。

另外一个常见的思路就是将字符串与可以获得类对象的函数进行映射 std::map<std::string, std::function<void*()>> string_objcreator_map ,如此,我们便可以通过字符串获取可以构造所需要的类对象的函数,实现从字符串到类对象的获取。

static std::shared_ptr<void> classFromName(std::string str)
  if(class_map.find(str)==class_map.end()) return nullptr;
  return class_map[str]();
#include <iostream>
#include <map>
#include <utility>
#include <string>
#include <functional>
#include <memory>
class Product{
    public: 
        using Ptr=std::shared_ptr<Product>;
        virtual void makeProduct()=0;
class ProductA : public Product {
    public:
        virtual void makeProduct()
            std::cout<<"Make Product A!"<<std::endl;
static std::map<std::string, std::function<std::shared_ptr<void> ()>> class_map;
static std::shared_ptr<void> classFromName(std::string str)
  if(class_map.find(str)==class_map.end()) return nullptr;
  return class_map[str]();
class Register{
public:
  Register(std::string str, std::function<std::shared_ptr<void>()> func)
    class_map.insert(std::make_pair(str, func));
#define REGISTER(classname) \
        class Register##classname { \
            public:                  \
            static std::shared_ptr<classname> instance(){  \
              return std::make_shared<classname>();       \
       auto temp = Register(std::string(#classname), Register##classname::instance);
REGISTER(ProductA)
int main()
  std::shared_ptr<ProductA> temp1=std::static_pointer_cast<ProductA>(classFromName("ProductA"));
  temp1->makeProduct();

我们需要在main函数之前将字符串和函数之间的关系准备好,即在main函数之前进行注册。在这里,为了进行注册,利用了全局变量的构造函数在main函数之前调用这个特点。在C++反射机制的实现,还有更多的在main函数之前执行一些动作的方式。
另外这里REGISTER宏中并不是直接定义构造对象的函数,而是定义了一个类,以从中获取对象instance,这样在注册多个类的时候,instance函数不至于冲突。

上面只有一个类型,我们其实没有必要根据字符串来获取对象,可以直接构造。而这里的这种注册机制的真正的应用场景更多是结合了工厂模式。而上面例子里的宏也主要是为了工厂模式中众多的重复代码准备的。

想象一下在有些场景下,有多种类型的对象可以创建,而我们需要做的就是根据需要选择合适的类型进行对象构造。比如,A和B程序员分别写了一个工厂用于A和B产品的生产,但是老板没有拿定主意用哪一个。于是,我们不能直接在代码里面写明用的哪种,而是留一个可选的结构来根据条件来实现。

// reflection_template.h
#ifndef _REFLECTION_TEMPLATE_H_
#define _REFLECTION_TEMPLATE_H_
#include <iostream>
#include <map>
#include <utility>
#include <string>
#include <functional>
#include <memory>
class Product{
    public: 
        using Ptr=std::shared_ptr<Product>;
        virtual void makeProduct()=0;
class ProductA : public Product {
    public:
        virtual void makeProduct()
            std::cout<<"Make Product A!"<<std::endl;
class ProductB : public Product {
  public:
        virtual void makeProduct()
            std::cout<<"Make Product B!"<<std::endl;
class Factory{
    public:
          using Ptr=std::shared_ptr<Factory>;
          virtual Product::Ptr createProduct()=0;
class ProductAFactory : public Factory
    public:
        virtual Product::Ptr createProduct(/* args */)
          return std::make_shared<ProductA>();
class ProductBFactory : public Factory {
    public: 
        virtual Product::Ptr createProduct(){
            return std::make_shared<ProductB>();
static std::map<std::string, std::function<std::shared_ptr<void> ()>> class_map;
static std::shared_ptr<void> classFromName(std::string str)
  if(class_map.find(str)==class_map.end()) return nullptr;
  return class_map[str]();
class Register{
public:
  Register(std::string str, std::function<std::shared_ptr<void>()> func)
    class_map.insert(std::make_pair(str, func));
#define REGISTER(classname) \
        class Register##classname { \
            public:                  \
            static std::shared_ptr<classname> instance(){  \
              return std::make_shared<classname>();       \
       auto temp##classname= Register(std::string(#classname), Register##classname::instance);
REGISTER(ProductAFactory)
REGISTER(ProductBFactory)
#endif
#include "reflection_template.h"
int main()
  std::shared_ptr<ProductAFactory> tempA=std::static_pointer_cast<ProductAFactory>(classFromName("ProductAFactory"));
  tempA->createProduct()->makeProduct();
  std::shared_ptr<ProductBFactory> tempB=std::static_pointer_cast<ProductBFactory>(classFromName("ProductBFactory"));
  tempB->createProduct()->makeProduct();

在这里实现了两个工厂,这里的工厂类可能被不同的程序员实现在不同的文件中。但是只要在实现完成之后利用REGISTER宏在全局的class_map中进行注册,即可通过classFromName得到构造对象的函数,进行对象构造。

参考:
C++反射机制的实现

String lv要获取类型的类名称 = "app.WJJL文件夹类"; //获取(app.WJJL文件夹类)所在的程序集名称。方法:随便使用一个相同命名空间的类(如此处的app.RYL人员类)来获取类所在程序集名称 String lv类所在程序集名称 = typeof(app.RYL人员类).Assembly.FullName);  //System.Type.GetType( 采用如下宏定义即可,这个宏定义将表达式x直接转换为对应的字符串:  #define varName(x) #x #define printExp(exp) cout<<#exp<<"为:\t\t"<<(exp)<<endl #define printExpToString(     问题的起因是,我在做一个demo,有一个对象基类,以及一堆派生出的子对象,比如球体、立方体之类的对象。还有一个对象管理类,用于存储场景中的所有对象。那么在初始化的时候,代码是这么写的: class ObjectInfo private: vector&lt;Object*&gt; vecObjs; public: void Init() vector&lt;strin... typeid 运算符用来获取一个表达式的类型信息。类型信息对于编程语言非常重要,它描述了数据的各种属性: 对于基本类型(int、float 等C++内置类型)的数据,类型信息所包含的内容比较简单,主要是指数据的类型。 对于类类型的数据(也就是对象),类型信息是指对象所属的类、所包含的成员、所在的继承关系等。 类型信息是创建数据的模板,数据占用多大内存、能进行什么样的操作、该如何操作等,这... 今天在看代码中,看到了一个很不错的工具函数typeid().name(),可以用来返回变量的数据类型,很实用。下面来具体学习一下该函数。首先来看typeid操作符,其返回结果是名为type_info的标准库类型对象的引用。type_info中存储特定类型的有关信息,定义在typeinfo头文件中。下面来看typeid().name(),用于获得表达式的类型,以c-style字符串形式返回类型名。用 以前我写过关于c++11新特性的第一部分,这是C++11新特性介绍的第二部分,涉及到C++11这次更新中较为重要的特性类型推断(auto)与类型获取(decltype)。 不想看toy code的读者可以直接拉到文章最后看这部分的总结。 简单的类型推断 C++11新标准中增加了auto类型说明符,可以让编译器帮我们分析表达式的类型。 double val1 = 1.1, val2 = 2... 复杂部分略去,摘录要素如下:1.typeid是C++的关键字之一,等同于sizeof这类的操作符。2.typeid操作符的返回结果是名为type_info的标准库类型对象的引用(在头文件typeinfo中定义)3.C++并没有规定typeid实现标准,各个编译器可能会不一样。4.编译器会为每一种typeid操作的类型生成一份保存在数据段的type_info数据。5.每种类型的type_info数... c++运行时反射实现原理实现 一直在研究如何巧妙地在c++语言层面上实现反射功能,boost库内有一个magic_get的反射,但是它是基于编译时的模板反射,给使用者的感觉来说,虽然是非侵入式的,但是使用上不够灵活,下面直接上代码,看看运行时的反射是怎么实现的。 c++11运行时反射代码实现 //main.cpp #include <iostream> #include <map> #include <vector> #include <algorithm> 背景需要根据配置文件中的插件名字获取插件实例,从而需要维护<插件名字,插件实例>的映射关系。 当有新插件加入项目时,每次都需要在该映射关系中插入一条信息。为了避免避免此操作,通过定义宏 自动完成 新插件的注册功能。设计思想每个插件在全局域中定义一个注册类,在该注册类的构造函数中将<插件名字,插件实例>插入全局的map中, 在全局域定义该注册类的一个实例,从而调用构造函数,在map中插入该 折腾C++类型系统是一个很有意思的事情。当钻进去之后就会发现,一些原先比较晦涩的基本概念,在研究的过程中都清晰了不少。 check_type的实用价值在于,可以利用它清晰的看见C++中一些隐藏的类型变化。比如完美转发时的引用折叠。 在实现check_type的过程中,用到了不少泛型,甚至元编程的小技巧,充分运用了C++在预处理期、编译期和运行期(RAII)的处理能力。虽然这些代码仅是学习研究时的兴趣之作,实际项目中往往typeid的返回结果就足够了,但上面的不少技巧对一些现实中的项目开发也有一定的参考和 转载于: https://blog.csdn.net/Scythe666/article/details/51718864 Java中有天然的反射机,因为Java本身就是半编译语言,很多东西可以在运行时来做,但是c++就不同了。要建立c++的反射机,就需要登记每个类名与 创建类实例的回调函数 的对应关系。 首先抛出一个问题:如何通过类的名称字符串来生成类的对象。比如有一个类ClassA,... 和网上大多数实现一样,本文也采用工厂方法来实现对象的动态创建,唯一不同的在于,本文的实现优化了类的注册,使用起来更为简单。废话不多说,直接上代码(这也没什么可说的,看代码更加直观)。 DynamicFactory.h文件,需要支持动态创建对象的地方,包含此文件,然后继承DynamicCreate即可。 #ifndef __DYNAMIC_FACTORY_H__ #define __DYNAMI 文章目录反射反射概述获取Class对象的三种方法:通过Class.forName()获取class对象,它会把参数指定的类加载到内存中反射类class的信息class对象方法 - 01获取反射类的代码示例通过反射技术访问类的字段(属性方法)并赋值class对象方法 - 02通过反射技术反射类的字段(属性)通过反射技术反射方法Class对象方法 - 03通过反射技术反射类的方法 反射就是根据字节码文件(Class),反射类的信息、字段、方法、构造方法等类的内容,然后根据字节码文件来创建对象,调