无基类参数的自注册工厂实现问题求助
自注册工厂模式未注册问题的解决方案
问题根源分析
- 子类注册代码未被实例化:测试文件仅包含
baseclass.h,未引入objecta.h。编译器仅在看到Registrar<ObjectA>的具体使用时,才会实例化其静态成员registered,进而触发registerT()完成注册逻辑。 - 构造函数调用错误:
ObjectA的构造函数未调用基类Registrar<ObjectA>的构造函数,而只有Registrar能合法创建Key并传递给BaseClass的构造函数。 - 测试代码笔误:调用
DeviceCommunication::make属于拼写错误,应为BaseClass::make。 - 类型名匹配风险:依赖
typeid+demangle获取类名,在部分编译器下可能返回包含命名空间或修饰符的字符串,导致工厂查找失败。
分步修复方案
1. 确保测试文件包含子类头文件
修改测试文件selfregisteringfactory.test.cpp,添加objecta.h的引用,强制编译器实例化注册代码:
#include "catch2/catch.hpp" #include "catch/fakeit.hpp" #include "baseclass.h" #include "objecta.h" // 必须包含子类头文件,触发注册逻辑 using namespace fakeit; TEST_CASE( "TEST SelfRegisteringFactory class." ) { SECTION("Test if adding an ObjectA to the factory is possible.") { auto objA = BaseClass::make("ObjectA"); // 修正笔误:DeviceCommunication -> BaseClass REQUIRE(objA->getType() == "ObjectA"); } }
2. 修正ObjectA的构造函数
ObjectA继承自Registrar<ObjectA>,必须调用基类构造函数以正确初始化BaseClass:
objecta.cpp:
#include "objecta.h" #include <iostream> // 显式调用基类Registrar的构造函数,传递合法的Key给BaseClass ObjectA::ObjectA() : BaseClass::Registrar<ObjectA>() {} void ObjectA::process(){ std::cout << "This is a process." << std::endl; } std::string ObjectA::getType(){ return "ObjectA"; }
3. 替换类型名获取方式(可选但推荐)
为避免demangle带来的不确定性,改用子类静态方法指定注册名称:
- 在
ObjectA中添加静态方法:
class ObjectA: public BaseClass::Registrar<ObjectA>{ public: // ... 原有代码 ... static std::string getTypeName() { return "ObjectA"; } };
- 修改
SelfRegisteringFactory的registerT函数:
static bool registerT() { const auto name = T::getTypeName(); // 改用子类指定的名称 SelfRegisteringFactory::data()[name] = [](Args... args) -> std::unique_ptr<Base> { return std::make_unique<T>(std::forward<Args>(args)...); }; return true; }
4. 强制实例化注册模板(兜底方案)
若仍存在注册问题,可在测试文件中强制实例化Registrar<ObjectA>的静态成员:
// 强制编译器实例化注册逻辑 template class BaseClass::Registrar<ObjectA>;
内容的提问来源于stack exchange,提问作者jcracine
相关产品推荐
相关产品推荐

