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

1. 适用场景


c++开发过程中使用工厂模式创建各种类对象的时候可能需要写一堆的’if-else’函数来根据传入的参数类型创建不同的类对象; 尤其是多态的情况下返回基类指针的情况. 例如:

class B -> class A // B继承A
class C -> class A // C继承A

A *Create(type) 
{
    if (type == B) return new (std::nothrow) B;
    if (type == C) return new (std::nothrow) C;
    return nullptr;
}

以上场景在开发中很常见, 但是如果继承关系复杂, 这样的代码需要不停修改代码, 不是很合理. 比较好的方式是实现类似:

B *p = static_cast<B *>(Create("B"));
C *p = static_cast<B *>(Create("C"));

这样的效果. 其实就是JAVA中的反射机制的体现, 实际c++本身是不支持的, 但是可以通过曲线救国的方式来实现.

2. 实现思路


核心: 通过回调函数来实现创建.
步骤: 1> 创建一个单例工厂类, 类中维护一个类名和创建对应类的回调函数的映射关系(map) 2> 需要创建的时候根据传入的类名参数查找对应的回调函数来创建类

3. 具体实现代码


main.cpp

#include "class_factory.h"

class CReflex
{
public:
    int RunTest()
    {
        std::cout << "Class Created. Perfect Running." << std::endl;
        return 0;
    }
};

SIM_OBJECT_CREATE_METHOD_REGISTER(CReflex);

int main(int argc, char **argv)
{
    CReflex *pReflex = static_cast<CReflex *>(ClassFactory::GetInst().Create("CReflex"));
    return pReflex->RunTest();    
}

class_factory.h

#ifndef CLASS_FACTORY_H
#define CLASS_FACTORY_H

#include <string>
#include <iostream>
#include <unordered_map>

typedef void *(*CLASS_CREATE_FN)();

class ClassFactory
{
public:
    static ClassFactory &GetInst();    

public:
    void *Create(const std::string &className);
    void RegistClass(const std::string &className, CLASS_CREATE_FN fn);

private:
	ClassFactory() = default;
	~ClassFactory() = default;
	ClassFactory(const ClassFactory &) = delete;
	ClassFactory &operator=(const ClassFactory &) = delete;

private:
    std::unordered_map<std::string, CLASS_CREATE_FN> m_mpObjName2Method;
};

class ClassRegisterAction
{
public:
    ClassRegisterAction(const std::string &className, CLASS_CREATE_FN fn);
};

#define SIM_OBJECT_CREATE_METHOD_REGISTER(className) \
        className *ClassCreate##className() \
        { \
            return new (std::nothrow) className; \
        } \
        ClassRegisterAction g_ClassRegisterAction##className(#className, (CLASS_CREATE_FN)ClassCreate##className);

#endif // CLASS_FACTORY_H

class_factory.cpp

#include "class_factory.h"

/// Class ClassFactory
ClassFactory &ClassFactory::GetInst()
{
    static ClassFactory factoryInst;
    return factoryInst;
}

void *ClassFactory::Create(const std::string &className)
{
    auto it = m_mpObjName2Method.find(className);
    if (it == m_mpObjName2Method.end()) {
        return nullptr;
    } else {
        return it->second();
    }
}

void ClassFactory::RegistClass(const std::string &className, CLASS_CREATE_FN fn)
{
    m_mpObjName2Method[className] = fn;    
}

/// Class ClassRegisterAction
ClassRegisterAction::ClassRegisterAction(const std::string &className, CLASS_CREATE_FN fn)
{
    ClassFactory::GetInst().RegistClass(className, fn);  
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
C++中没有像Java和C#等语言那样的反射机制,因此无法直接根据类名字符串创建。不过可以通过一些技巧实现似的功能。 一种常见的方法是使用工厂模式。首先定义一个或接口,所有需要创建实现该基或接口。然后创建一个工厂,该工厂一个静态方法,接收一个字符串作为参数,根据这个字符串来决定创建哪个对象。在这个静态方法中,使用if/else或switch/case等语句来判断要创建哪个对象,最后返回创建的对象。使用时,通过工厂创建对象即可。 下面是一个简单的示例代码: ```cpp class Base { public: virtual void func() = 0; }; class Derived1 : public Base { public: virtual void func() { std::cout << "Derived1" << std::endl; } }; class Derived2 : public Base { public: virtual void func() { std::cout << "Derived2" << std::endl; } }; class Factory { public: static Base* create(const std::string& name) { if (name == "Derived1") { return new Derived1(); } else if (name == "Derived2") { return new Derived2(); } else { return nullptr; } } }; int main() { Base* obj1 = Factory::create("Derived1"); obj1->func(); // 输出 Derived1 Base* obj2 = Factory::create("Derived2"); obj2->func(); // 输出 Derived2 return 0; } ``` 在上面的示例代码中,我们创建一个Base,以及两个派生Derived1和Derived2,它们都实现了Base的纯虚函数func。然后创建一个工厂Factory,其中的静态方法create接收一个字符串作为参数,根据这个字符串来创建对象。在main函数中,我们通过工厂创建对象,并调用其func方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SuperYang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值