我正在尝试创建一个将字符串映射到工厂函数的全局映射。这允许我让一个构建器函数从ini文件中读取一个键,然后将该相关部分的ini文件传递给正确的工厂函数。以下是带有全局映射的标题中的代码:
typedef Primitive* (*factory_func_t)(const ::INI&, const std::string&);
const std::map<std::string, factory_func_t> factory_funcs = {
{ SphereFactory::ID, &SphereFactory::create_sphere },
{ QuadFactory::QUAD_ID, &QuadFactory::create_quad },
{ QuadFactory::PQUAD_ID, &QuadFactory::create_pquad }
};
以下是其中一个工厂类的示例:
class SphereFactory
{
public:
static const std::string ID;
static Sphere* create_sphere(const ::INI&, const std::string& section);
SphereFactory() = delete;
private:
static const std::string CENTER_KEY;
static const std::string RADIUS_KEY;
};
const std::string SphereFactory::ID = "Sphere";
const std::string SphereFactory::CENTER_KEY = "Center";
const std::string SphereFactory::RADIUS_KEY = "Radius";
这一切在编译时给我一个错误:
error: could not convert `{{cg::prim::factory::SphereFactory::ID,
cg::prim::factory::SphereFactory::create_sphere},
{cg::prim::factory::QuadFactory::QUAD_ID,
cg::prim::factory::QuadFactory::create_quad},
{cg::prim::factory::QuadFactory::PQUAD_ID,
cg::prim::factory::QuadFactory::create_pquad}}'
from `<brace-enclosed initializer list>'
to `const std::map<std::basic_string<char>, cg::Primitive* (*)(const INI&,
const std::basic_string<char>&)>'
以上所有代码都在cg::prim::factory
命名空间中,以防有所作为。 Quad
和Sphere
都继承自Primitive
。我正在使用g++ -O3 -Wall -Wextra -pedantic -std=c++11
进行编译。
为什么不编译?
答案 0 :(得分:3)
您正在尝试使用协变返回类型:typedef
用于Primitive *
但工厂返回Sphere *
等。您可能包含返回基类型的替代包装工厂函数
实际上,C ++看不到返回基指针和派生指针的函数之间的关系。只允许virtual
函数以这种方式“转换”,而工厂不能是虚拟的。 (或者至少,在C ++中,不鼓励使用具有虚函数的工厂对象。这在Java中是典型的,但这里的包装函数会更好。)
由于初始化程序列表仍处于起步阶段,因此调试(并解决可能仍存在的潜在编译器错误)的一种方法是尽可能手动编译:
const std::map<std::string, factory_func_t> factory_funcs = {
{ SphereFactory::ID, (factory_func_t) &SphereFactory::create_sphere },
{ QuadFactory::QUAD_ID, (factory_func_t) &QuadFactory::create_quad },
{ QuadFactory::PQUAD_ID, (factory_func_t) &QuadFactory::create_pquad }
};