Is it possible to create a C ++ factory system that can create an instance of any type of "registered" objects, regardless of inheritance?

I spent all my day studying this topic, so with some scattered knowledge on this topic, I came to you with this request. Let me describe what I'm trying to accomplish, and perhaps you can either offer a solution to the immediate question, or another way to completely solve the problem.

I am trying to imitate something related to how XAML files work in WPF , where you essentially instantiate an object tree from an XML definition. If this is not correct, report it. This problem is otherwise not related to WPF , C #, or something controlled - I mention this only because it is a similar concept.

So, I already created an XML parser class and generated a node tree based on ObjectNode objects. An ObjectNode object contains a string value of type , and they have std :: vector children of ObjectNode objects.

The next step is to create an instance of the object tree based on the data in the ObjectNode tree. This intermediate ObjectNode tree is necessary because the same ObjectNode tree can be created several times or delayed as needed. The tree of created objects is such that the nodes in the tree are descendants of a common base class, which can now be called MyBase . Leaf nodes can be of any type, not necessarily obtained from MyBase .

To make this more complicated, I will not know what types of objects can be involved in the tree, so I need to allow registration of new types with the factory.

I am aware of a factory upgrade. Their documents have an interesting little design paragraph on this page :

<i> o We may need a factory that takes some arguments that are redirected to the constructor,
o we probably want to use smart pointers,
o we may want several member functions to create objects of different types,
o we may not need a polymorphic base class for objects,
o, as we will see, we donโ€™t need the factory base class at all,
o we could just call the constructor - without # new # to create an object on the stack and
o Finally, we might want to use individual memory management.

I might not get it all right, but it seems like I'm arguing that what I'm trying to do can be achieved using boost factory. But all the examples I cite seem to describe factories where all the objects are made from the base type.

Any advice on this would be greatly appreciated.

Thank you for your time!

+4
source share
4 answers

Define a typedef for factory methods, for example:

typedef void* (*FactoryMethod)(const vector<string>& parameters); 

In other words, each factory method returns a pointer to something (a pointer to void) and takes as a parameter a const vector from strings.

Registration data is as follows:

 std::map<string, FactoryMethod> globalFactoryMethods; 

... where the key is the type string , and the value is a pointer to the corresponding factory method. When you have a new type with a new factory method, "register" it by adding it to the map (at runtime).

A design using registered factory methods might look like this (pseudo-code):

 foreach (Node node in nodes) { string type = node.type; FactoryMethod factoryMethod = globalFactoryMethods[type]; void* constructedLeaf = (*factoryMethod)(node.nParameters, node.pParameters); //do something here with constructed leaf } 

Leaf nodes can be of any type, not necessarily derived from MyBase.

This is a problem in C ++: if you do not know what it is, then how do you delete them?

C # (unlike C ++) can delete things without knowing what they are, or rather, it is not necessary to delete things: because it is managed memory, and all this is a subclass of System.Object .

+2
source

Itโ€™s very good that you described your problem :)

The idea of โ€‹โ€‹creating a factory of the possibility of creating any type, of course, is very attractive, but it is complex and not needed. I understand the appeal of void* , unfortunately, it is not as smooth as it seems. The only thing you can do with such a beast is to include it in the correct pointer ... and this requires knowing what type is at compile time!

Suppose I have std::vector<void*> and I ask you to print the contents of this vector, what are you going to do?

This is perfectly acceptable to get people to create classes that they inherit from the base class you are developing with the goal of simply dealing with the factory.

 struct Object: boost::noncopyable { virtual Object* clone() const = 0; virtual ~Object() {} }; 

This is a very small restriction than requiring inheritance from this class. In return, you get a virtual destructor and guarantee that the class can be copied polymorphically (thanks to the clone member function) to avoid the problem of trimming objects.

I think you should read some design patterns:

  • The prototype is widely used to implement Factory, although this is not the only way.
  • Factory , you seem to already know, it is possible that AbstractFactory will help you too.
  • Composite is required for working with object trees.
  • Visitor really helps define an advanced compatible way to work with Composite
+1
source

if I think I correctly understood something like this:

 void register(string constructor, void*(*method)(...)); // put in map template<class T> T* new_(string subclass, ...) { return static_cast<T*>(constructors_[subclass](...)); } 
0
source

I canโ€™t really understand your question, but from the topic, I think that you are trying to create an arbitrary registered object, maybe you can look at the "prototype" design template
Click here for the almighty wiki

0
source

Source: https://habr.com/ru/post/1310692/


All Articles