在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然

Is it possible to create a new instance of base class based on a given identifier and vice versa in C++

本文关键字:基类 创建 标识符 新实例 反之亦然 实例 是否 C++      更新时间:2023-10-16

我有一个基类和多个子类对其进行扩展。我的目标是使用C++创建一个基于标识符的子类的新实例,反之亦然。我使用了一个类似于这样的切换用例语句:

std::shared_ptr<base> create(int id)
{
std::shared_ptr<base> p;
switch (id) {
case 0:
p = std::make_shared<derived1>();
break;
case 1:
p = std::make_shared<derived2>();
break;
default:
throw;
}
return p;
}

但我想要一种更优雅的方法,反之亦然。以下是我用Java编码的目标的工作实现:

static BiMap<Integer, Class<? extends Base>> map = HashBiMap.create();
static {
map.put(0, Derived1.class);
map.put(1, Derived2.class);
}
static Base createInstance(int id) throws IllegalAccessException, InstantiationException {
return map.get(id).newInstance();
}
static int getId(Base instance) {
return map.inverse().get(instance.getClass());
}

提前谢谢!

C++不像Java那样有元类。因此,与Java代码最接近的C++等价物看起来是这样的:

#include <map>
#include <memory>
class Base
{
public:
...
virtual int getId() const = 0;
};
class Derived1: public Base
{
public:
...
int getId() const override { return 0; }
};
class Derived2: public Base
{
public:
...
int getId() const override { return 1; }
};
...
using createFunc = std::shared_ptr<Base>(*)();
static std::map<int, createFunc> myMap
{
{0, []() -> std::shared_ptr<Base> { return std::make_shared<Derived1>(); }},
{1, []() -> std::shared_ptr<Base> { return std::make_shared<Derived2>(); }}
...
};
static std::shared_ptr<Base> createInstance(int id)
{
auto iter = myMap.find(id);
if (iter == myMap.end())
throw ...;
return iter->second();
}
static int getId(Base* instance)
// or: static int getId(std::shared_ptr<Base> &instance)
{
return instance->getId();
}

实时演示

我会有一个类似_getId()的虚拟函数。然后,您可以让每个派生类返回其唯一标识符:

class base {
...
virtual int _getId() = 0;
};
class derived1: public base {
...
int _getId() { return 1; }
};
...

所以你的静态基础getId()可能看起来像:

static int getId(base *instance) {
return instance->_getId();
}