有没有办法基于文本文件动态创建对象?
Is there a way to dynamically create objects based on a text file?
在构建模拟器应用程序时,我希望能够将我目前正在处理的模拟保存/加载到文本文件中。我有一个文本文件的标准,它实际上是一个csv,其中每行对应于模拟的一个组件,每行的第一个条目是唯一标识给定组件的字符串。我希望能够解析此文本文件,并根据第一个条目动态创建相应组件类型的对象。
这些组件都是在它们自己的类中定义的,这些类从Base
类扩展而来。 此解析的结果应为我提供一个Base
指针列表,这些指针是指向从文本文件解析的各种组件的多态指针。这个问题最明显的解决方案是在组件的解析类型上有一个巨大的if-else:
Base* p;
if(type == "A"){
p = new A();
} else if(type == "B"){
p = new B();
} ...
不过,这非常乏味。所以我的下一个解决方案是有一个映射,这样条目的键是唯一标识符字符串,值是指向函数的函数指针,该函数返回指向相应组件的新实例的多态指针。这样我就可以从文本文件中解析出type
字符串并运行如下行:
Base* p = functionMap.at(type)();
其中,映射中的每个函数都有一个定义,如下所示:
//Note that this doesn't need to be scoped off of each class, I've only
//done this to make it clear that this function could be an overridden
//function from the base class in the children if that brings a solution
Base* A::generate(){
return new A();
}
这一切都很好,但是除了在执行其他任何操作之前将每个组件的generate
函数都添加到地图中,insert
否则我无法将每个组件添加到地图中。在这一点上,我仍然会为每个组件进行硬编码,我不妨只使用 if-else。
我可以在每个标头中定义生成函数(尽管它们都相同,并且它有效地只是将硬编码抽象到多个文件而不是一个文件(,如果我可以自动将类注册到映射中。
有没有办法使用函数指针映射解决方案?或者更重要的是,有没有办法在解析器中实现这种行为,而不涉及每个组件的硬编码?到目前为止,软件的其余部分可以适应自动定义的任何新组件,因此不必每次制作新组件时都手动添加组件真是太好了。
一个老问题的答案。 .
.在下面的代码中,您有一个可以通过std::initalizer_list
和"add"函数生成的类的静态列表,您可以在其中添加以后的更多类创建者。
此外,我用std::any
解决了构造函数中不同签名的问题
也许这对面临同样问题的其他人来说很有趣。
#include <iostream>
#include <map>
#include <utility>
#include <any>
// Some demo classes ----------------------------------------------------------------------------------
struct Base {
Base(int d) : data(d) {};
virtual ~Base() { std::cout << "Destructor Basen"; }
virtual void print() { std::cout << "Print Basen"; }
int data{};
};
struct Child1 : public Base {
Child1(int d, std::string s) : Base(d) { std::cout << "Constructor Child1 " << d << " " << s << "n"; }
virtual ~Child1() { std::cout << "Destructor Child1n"; }
virtual void print() { std::cout << "Print Child1: " << data << "n"; }
};
struct Child2 : public Base {
Child2(int d, char c, long l) : Base(d) { std::cout << "Constructor Child2 " << d << " " << c << " " << l << "n"; }
virtual ~Child2() { std::cout << "Destructor Child2n"; }
virtual void print() { std::cout << "Print Child2: " << data << "n"; }
};
struct Child3 : public Base {
Child3(int d, long l, char c, std::string s) : Base(d) { std::cout << "Constructor Child3 " << d << " " << l << " " << c << " " << s << "n"; }
virtual ~Child3() { std::cout << "Destructor Child3n"; }
virtual void print() { std::cout << "Print Child3: " << data << "n"; }
};
using UPTRB = std::unique_ptr<Base>;
template <class Child, typename ...Args>
UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }
// The Factory ----------------------------------------------------------------------------------------
template <class Key, class Object>
class Factory
{
std::map<Key, std::any> selector;
public:
Factory() : selector() {}
Factory(std::initializer_list<std::pair<const Key, std::any>> il) : selector(il) {}
template<typename Function>
void add(Key key, Function&& someFunction) { selector[key] = std::any(someFunction); };
template <typename ... Args>
Object create(Key key, Args ... args) {
if (selector.find(key) != selector.end()) {
return std::any_cast<std::add_pointer_t<Object(Args ...)>>(selector[key])(args...);
}
else return nullptr;
}
};
int main()
{
// Define the factory with an initializer list
Factory<int, UPTRB> factory{
{1, createClass<Child1, int, std::string>},
{2, createClass<Child2, int, char, long>}
};
// Add a new entry for the factory
factory.add(3, createClass<Child3, int, long, char, std::string>);
// Some test values
std::string s1(" Hello1 "); std::string s3(" Hello3 ");
int i = 1; const int ci = 1; int& ri = i; const int& cri = i; int&& rri = 1;
UPTRB b1 = factory.create(1, 1, s1);
UPTRB b2 = factory.create(2, 2, '2', 2L);
UPTRB b3 = factory.create(3, 3, 3L, '3', s3);
b1->print();
b2->print();
b3->print();
b1 = factory.create(2, 4, '4', 4L);
b1->print();
return 0;
}
- C++ 使用存储在动态数组中的文本文件中的数据查找模式
- 生成文件:动态源文件名和对象目录
- 提示存档文件中的动态库依赖项
- 如果包含映射的静态库与可执行文件和动态库链接,静态映射(变量)是否会被多次释放?
- 从 C 可执行文件加载动态库时收到错误C++"undefined symbol"
- 调用函数一次用于动态链接库,一次从可执行文件调用函数
- 如何在Windows上链接动态构建的cmake文件
- 仅使用生成文件动态编译选定的文件
- 无法在二进制文件中存储动态数组
- 有没有办法基于文本文件动态创建对象?
- 将动态方法添加到类中:使用宏函数到头文件中
- 在动态加载的位置无关的可执行文件中分离错误
- 如何从文件读取到动态分配的指向结构的指针链表中?
- 对应于 stdio.h 的库文件是动态链接还是静态链接
- C++如何从文件动态创建类的多个对象
- 使用数据文件动态分配数组
- Netbeans/C++:将2个项目链接在一起(可执行文件/动态库)
- 是否可以从XML文件动态构建函数声明
- 如何创建*.所以文件动态链接OpenCV为Android
- 从流或文件动态反序列化数据