Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/44.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
根据C++中的字符串值创建类对象实例的好方法?_C++_Factory Pattern - Fatal编程技术网

根据C++中的字符串值创建类对象实例的好方法?

根据C++中的字符串值创建类对象实例的好方法?,c++,factory-pattern,C++,Factory Pattern,有关问题,请参见代码剪报: class Base; typedef Base* BasePtr; template<typename D> BasePtr CreateDerivedClass() { return new D(); } class D1 : public Base { .... }; class D2 : public Base { .... } void main() { std::string derived_name = {&quo

有关问题,请参见代码剪报:

class Base; 
typedef Base* BasePtr; 

template<typename D>
BasePtr CreateDerivedClass() {
    return new D();
}

class D1 : public Base {
....
};

class D2 : public Base {
....
}

void main() {
    std::string derived_name = {"D1", "D2"}; 
    std::vector<BasePtr> derived_vec; 
    for (auto& name : derived_name) {
// QUESTION: Other than factory design pattern, how can I pass the derived 
// class typename which is the value of string "name" to CreateDerivedClass<name> ?
        derived_vec.push_back(CreateDerivedClass<name>()); 
    }
}

注意:在这里,我不想使用工厂设计模式,它在定义期间需要派生类寄存器本身。

在编译时应该知道模板的类型t,这是因为编译器需要创建一个与类/函数的类型匹配的代码。这是C++中模板的工作方式。
如果派生的名字将由不是已知类型的值D8组成,我们就有麻烦了。

< P>模板的类型T应该在编译时知道,这是因为编译器需要创建与类型/类型的Type /函数实现匹配的代码。这就是C++中模板的工作方式。
如果派生的_名称包含的值D8不是已知的类型,我们将遇到问题。

编译时必须知道模板参数值。无法在运行时直接将字符串转换为模板参数中使用的类型。您必须在运行时比较字符串值,以决定调用哪个CreateDerivedClass专门化

例如,处理此问题的最简单方法是使用std::map,其中的元素包含指向您希望能够调用的专用函数的指针,例如:

使用createFuncType=BasePtr*; std::map createFuncs; createFuncs[D1]=&CreateDerivedClass; createFuncs[D2]=&CreateDerivedClass; ... 然后你可以这样做:

std::字符串派生的_名称[]={D1,D2}; std::向量派生的向量; 自动命名:派生的名称(&U){ 派生向量推送返回创建函数[名称]; } 在这种情况下,实在没有其他选择

也就是说,您应该使用std::unique_ptr而不是原始的Base*指针,例如:

包括 包括 包括 包括 阶级基础{ 公众: virtual~Base=默认值; }; 使用BasePtr=std::unique\u ptr; 使用createFuncType=BasePtr*; 样板 BasePtr CreateDerivedClass{ 返回std::使_唯一; } D1类:公共基地{ ... }; D2类:公共基地{ ... } ... int main{ std::map createFuncs; createFuncs[D1]=&CreateDerivedClass; createFuncs[D2]=&CreateDerivedClass; ... 字符串派生的_名称={D1,D2,…}; std::向量派生的向量; 自动命名:派生的名称(&U){ 派生向量推送返回创建函数[名称]; } ... 返回0; }
模板参数值必须在编译时已知。无法在运行时直接将字符串转换为模板参数中使用的类型。您必须在运行时比较字符串值,以决定调用哪个CreateDerivedClass专门化

例如,处理此问题的最简单方法是使用std::map,其中的元素包含指向您希望能够调用的专用函数的指针,例如:

使用createFuncType=BasePtr*; std::map createFuncs; createFuncs[D1]=&CreateDerivedClass; createFuncs[D2]=&CreateDerivedClass; ... 然后你可以这样做:

std::字符串派生的_名称[]={D1,D2}; std::向量派生的向量; 自动命名:派生的名称(&U){ 派生向量推送返回创建函数[名称]; } 在这种情况下,实在没有其他选择

也就是说,您应该使用std::unique_ptr而不是原始的Base*指针,例如:

包括 包括 包括 包括 阶级基础{ 公众: virtual~Base=默认值; }; 使用BasePtr=std::unique\u ptr; 使用createFuncType=BasePtr*; 样板 BasePtr CreateDerivedClass{ 返回std::使_唯一; } D1类:公共基地{ ... }; D2类:公共基地{ ... } ... int main{ std::map createFuncs; createFuncs[D1]=&CreateDerivedClass; createFuncs[D2]=&CreateDerivedClass; ... 字符串派生的_名称={D1,D2,…}; std::向量派生的向量; 自动命名:派生的名称(&U){ 派生向量推送返回创建函数[名称]; } ... 返回0; }
有许多方法可以从字符串值创建变量。请参阅strtoul,std::istringstream。由于没有指定变量的类型,请参见std::string::substr。虽然在定义过程中不必注册,但在某一点上仍然需要注册。我同意@Remy的观点,一个包含工厂函数的映射(由字符串化的类名键控)似乎是最好的方法。这张地图可以保存在一个地方。虽然类的自注册听起来更好,因为在实现另一个派生类时,您必须考虑这一点。我总是要在一个文件中管理它。^^^^注意:不适用于模板。谢谢大家的回答。谢谢@drescherjm,我想知道的是,我是否可以不用注册这个类就完成这个任务。现在我明白了这是不可能的。谢谢有许多方法可以从字符串值创建变量。请参阅strtoul,std::istringstream。因为你没有指定
变量的类型,另请参见std::string::substr。虽然在定义过程中不必注册,但在某一点上仍然需要注册。我同意@Remy的观点,一个包含工厂函数的映射(由字符串化的类名进行键控)似乎是最好的方法。这张地图可以保存在一个地方。虽然类的自注册听起来更好,因为在实现另一个派生类时,您必须考虑这一点。我总是要在一个文件中管理它。^^^^注意:不适用于模板。谢谢大家的回答。谢谢@drescherjm,我想知道的是,我是否可以不用注册这个类就完成这个任务。现在我明白了这是不可能的。谢谢谢谢你回答这个问题。是的,我使用了工厂设计模式并应用了一个包含工厂功能的地图。我想弄清楚的是,如果不注册这个类,是否有可能做到这一点。现在很明显这是不可能的,我必须在某个地方注册课程。谢谢你回答这个问题。是的,我使用了工厂设计模式并应用了一个包含工厂功能的地图。我想弄清楚的是,如果不注册这个类,是否有可能做到这一点。现在很明显这是不可能的,我必须在某个地方注册这个课程。