IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 用c++11 实现类名反射对象 -> 正文阅读

[C++知识库]用c++11 实现类名反射对象

由于最近工作中用到工厂模式来创建不同的窗口对象在主窗口中显示, 以前遇到类似的情况我都是把所有需要创建的窗口类头文件都包含到主窗口MainWnd.cpp中, 这样每新增一个窗口, 就需要修改 MainWnd.cpp 。MainWnd.cpp 也就需要重新编译。?后来百度了下c++反射, 有用Qt 元对象机制的(Qt继承自QObject 的类是可以支持反射的); 有用模版实现的类工厂, 然后需要反射的类从该类继承; 也有模仿MFC 的(需要在类的声明和实现中加入相关宏)...? 感觉都有点麻烦。

后来再百度下有没有用 c++11, 或者 boost 实现的, 但好像没找到, 于是今天我闲着无聊就自己写一个基于C++11语法的类名反射。 最终成型后, 功能对于我来说已经满足。

用法是:

1> 在需要反射的类cpp 中调用宏 ReflectRegister 注册子类

2> 在策略函数中, 包含基类头文件,??然后根据子类的类名创建对象。

代码如下:

/*  @file ObjFactory.h
 *  @brief 根据子类名创建对象。可注册构造函数参数个数任意的类
 *
 *  用法:假设 BaseShape 有 2 个派生类: Rectangle 和 Triangle 。 3个类分别在不同的文件中
 *  , BaseShape 有个纯虚函数 virtual void draw() = 0;
 *  @code:
 *  // BaseShape.h
 *  class BaseShape
    {
    public:
        virtual void draw() = 0;
    };

    // Rectangle.cpp
    #include "BaseShape.h"
    #include "ObjFactory.h"

    ReflectRegister(Rectangle) // 注册矩形类
    class Rectangle : public BaseShape
    {
    public:
        Rectangle()
        {}

        void draw() override
        {
            qDebug("%s", qPrintable("I'm Rectangle"));
        }
    };

    // Triangle.cpp
    #include "BaseShape.h"
    #include "ObjFactory.h"

    ReflectRegister(Rectangle) // 注册三角形类
    class Triangle : public BaseShape
    {
    public:
        Triangle()
        {}

        void draw() override
        {
            qDebug("%s", qPrintable("I'm Triangle"));
        }
    };

    // main.cpp
    #include "BaseShape.h" // 只用包含基类头
    int main()
    {
        BaseShape* pBase;
        pBase = ObjFactory::createObj<BaseShape>("Rectangle");
        if (pBase != nullptr)
            pBase->draw();

        pBase = ObjFactory::createObj<BaseShape>("Triangle");
        if (pBase != nullptr)
            pBase->draw();
    }

    @endcode
 *  @author zhoumanman888@126.com
 *  @date 2021/7/24
 */
#ifndef ObjFactory_H
#define ObjFactory_H


#include <map>
#include <string>

/// 需要反射的类使用该宏注册
#ifndef ReflectRegister
#define ReflectRegister(YourClass, ...) \
    const int __type = ObjFactory::_RegClsFactoryFunc(#YourClass, (ObjFactory::_FunctionFactory)&_CreateObjFactory<YourClass, ##__VA_ARGS__>);
#endif

/// 对象工厂,根据类名创建
class ObjFactory
{
public:
    /// 可以保存带任何类型参数的函数指针
    typedef void*(*_FunctionFactory)();

    /// 根据类名创建 BaseClass 子类的对象
    template<class BaseClass, typename ...ArgType>
    static BaseClass* createObj(std::string className, ArgType... arg)
    {
        typedef BaseClass*(*_CreateFactory)(ArgType...);

        auto& _funcMap = _GetStaticFuncMap();
        auto iFind = _funcMap.find(className);
        if (iFind == _funcMap.end())
            return nullptr;
        else
            return reinterpret_cast<_CreateFactory>(_funcMap[className])(arg...);
    }

    /// 注册“创建类的对象的工厂函数”
    static int _RegClsFactoryFunc(std::string className, _FunctionFactory func)
    {
        _GetStaticFuncMap()[className] = func;
        return 0;
    }
private:
    /// 获取 函数名==>函数指针 的映射。
    static std::map<std::string, _FunctionFactory>& _GetStaticFuncMap()
    {
        static std::map<std::string, _FunctionFactory> _classMap;
        return _classMap;
    }
};


/// 对象创建模版函数, 用到了 c++11 的可变参数
template<class YourClass, typename ...ArgType>
YourClass* _CreateObjFactory(ArgType... arg)
{
    return new YourClass(arg...);
}

#endif // ObjFactory_H

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-25 11:28:13  更:2021-07-25 11:30:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 5:02:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码