使用索引创建类的对象
Creating object of a class using index
我有这样的类:Class1类别2类别3一年级Class5Class6.........ClassN
在其中一个函数中,我需要根据函数的输入参数创建类的对象。
例如,如果输入为1,则需要创建Class1对象,如果输入为2,则创建Class2对象。
是否可以不使用if条件创建对象?我不希望所有的课程都是这样。
由于使用了继承,因此需要一个工厂函数来生成任何派生类型…
template<typename T>
base * spawn ()
{
return new T();
}
…和支持operator[]
随机访问的容器。
如果需要不连续的索引,请选择映射:
std::map<int, base *(*)()> map_spawner =
{
{ 0, &spawn<child_1> },
{ 1, &spawn<child_2> }
};
如果索引是连续的,选择一个向量:
std::vector<base *(*)()> vec_spawner =
{
&spawn<child_1>,
&spawn<child_2>
};
工作示例:
#include <map>
#include <vector>
class base
{
public:
virtual ~base () = default;
public:
virtual int f () const = 0;
};
class child_1 : public base
{
public:
int f () const override { return 1; }
};
class child_2 : public base
{
public:
int f () const override { return 2; }
};
template<typename T>
base * spawn ()
{
return new T();
}
int main ()
{
// With a vector
std::vector<base *(*)()> vec_spawner =
{
&spawn<child_1>,
&spawn<child_2>
};
base * child = vec_spawner[0]();
// Do something with child here ...
delete child;
// With a map
std::map<int, base *(*)()> map_spawner =
{
{ 0, &spawn<child_1> },
{ 1, &spawn<child_2> }
};
child = map_spawner[1]();
// Do something with child here ...
delete child;
}
现在你可以使用用户输入来生成一个特定的实例。
如果你的派生类型构造函数不共享相同的参数,不幸的是,据我所知,你不能使用任何容器…我能想到的唯一的可能性是这样的(工作示例):
#include <utility>
class base
{
public:
virtual ~base () = default;
public:
virtual int f () const = 0;
};
class child_1 : public base
{
public:
int f () const override { return 1; }
};
class child_2 : public base
{
public:
child_2 (int i) { (void) i; }
public:
int f () const override { return 2; }
};
template<typename... Args>
base * spawn (int input, Args && ... args)
{
switch (input)
{
case 0: return new child_1 {};
case 1: return new child_2 { std::forward<Args>(args)... };
// ...
}
return nullptr;
}
int main ()
{
int input = 1;
base * child = spawn(input, 42);
// Do something with child here ...
delete child;
}
如果您的项目是windows dll,我有一个可能的解决方案:
为项目中的每个派生类定义一个工厂方法。创建Class1
对象的工厂方法应该命名为us1
(或者任何触发该对象创建的用户输入)。
然后使用GetProcAddress
API根据其名称获得工厂方法的地址(同样,名称是用户输入的)-获得后,只需调用它来创建对象。
一些代码片段来展示这个概念(因为你还没有发布你的代码,所以很难提出一些真实的建议)
class Base
{
public:
void foo() = 0;
}
class Derived1 : public Base
{
public:
void foo() {};
}
class Derived2 : public Base
{
public:
void foo() {};
}
extern "C"
{
void __declspec(dllexport) us1 (Base*& pObj)
{
pObj = new Derived1();
}
void __declspec(dllexport) us2 (Base*& pObj)
{
pObj = new Derived2();
}
}
然后在你的CPP文件中使用类似
的内容typedef void (__cdecl FUNCPROC)(Base*&);
string userInput;
cin >> userInput;
// get a handle to your dll memory (if this is a dll)
// assuming moduleHandle points to your dll memory
FUNCPROC* pProcAddr = GetProcAddress((HMODULE)moduleHandle, userInput);
现在pProcAddr
是一个基于用户输入的受尊重的工厂方法的指针。
得到正确的对象
Base* pTmp = NULL;
pProcAddr(pTmp);
现在我上面的建议是不完整的,还有更多的事情要处理(检查有效的用户输入,检查工厂方法是否存在于内存中,等等…),但它应该给你一个大致的想法。
我在很多情况下都使用了这段代码。
假设您的所有类Class1
~ ClassN
都派生自一个抽象基类class Base
。
#include <vector>
#include <memory>
#include <functional>
std::vector<std::function<std::shared_ptr<Base> ()>> CtorList = {
[] { return std::shared_ptr<Base>(new Class1); },
[] { return std::shared_ptr<Base>(new Class2); },
[] { return std::shared_ptr<Base>(new ClassN); },
};
// Create
std::shared_ptr<Base> p = CtorList[num - 1]();
(生活)
我建议使用从输入类型映射到工厂对象的映射。工厂对象有一个返回所需类型的虚方法。因此,每个类(Class1…ClassN)都有一个匹配的工厂类(FCi),该工厂类知道如何构造(Classi)的对象。
typedef std::map< Input, Factory > FactoryMap;
FactoryMap factoryMap;
void initFactoryMap()
{
factoryMap[ Input1 ] = new FactoryForClass1(); // subclass of Factory, implementing constructClass
factoryMap[ Input2 ] = new FactoryForClass2();
factoryMap[ Input3 ] = new FactoryForClass3();
...
}
AbstractClass *inputHandler( Input n )
{
return factoryMap[n]->constructClass( n ); // may not need to pass n in
}
我真的很感激您定义了这么多的类…但我更愿意定义一个单一的类与一个函数,将负责创建所需的表,我会试图找出一些逻辑的方式来创建/打印表,如果表是类似的…或者在最坏的情况下,我会使用switch
语句来选择创建/打印哪个表。
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 具有包含其他对象的类的对象创建顺序
- 为什么我们再次从结构对象创建结构变量?
- 将对象创建为全局/静态对象会崩溃,而本地对象不会崩溃
- 如何创建一个对象创建函数,该函数将由与其关联的名称调用?
- 如何为自定义模板对象创建专门的函数模板
- 对象创建错误的C++矢量
- 如何为Python Swigged C++对象创建和分配回调函数
- 在 C++ 中为 C 样式对象创建一个透明包装类
- 此类模板的对象创建如何工作?
- C++ 中的对象创建类型有什么区别?
- 未知大小的数组作为类成员,用于在运行时(对象创建时间)创建数组的对象
- 如何仅通过父类对象限制对象创建
- 在正确性或良好的代码结构方面,这种动态对象创建看起来如何
- 无法将类对象创建为另一个类的成员
- 如何从现有基类对象创建派生类对象
- 在 DTor 之前删除的静态对象创建的线程?
- C++:定义多个构造函数时的对象创建/销毁序列
- 从对象创建矢量包装器,该对象只允许使用索引访问向量
- 是否可以为CPP中的对象创建一组指针