Factory Pattern in C++: generating explicit createInstance()-Method automatically

為{幸葍}努か 提交于 2019-12-23 03:21:34

问题


i have the problem in writing a C++ framework, that users should have less overhead than possible to use it. Users can publish their work to the frameworks by creating a shared library that contains a class, which is derived by a frameworks' BaseClass and implementing an extern "C" createInstance()-method in order to return an instance its' derived class. So the framework can access the user class by calling the createInstance-Method through the shared library with dlsym().

class BaseClass{}
class UserClass : public BaseClass{}

extern "C"{  
   BaseClass* UserXcreateInstance(){
    return new UserClass();
   }                        
}

In framework:

typedef BaseClass* (*CreateInstance) ();
void* handle;
CreateInstance createInstance;
handle = dlopen( "libUserLibrary.so", RTLD_LAZY | RTLD_GLOBAL );
createInstance = reinterpret_cast <CreateInstance*> dlsym( handle, "UserXcreateInstance" );
BaseClass* userX = createInstance();

My Question: Is it possible to generate the UserXcreateInstance()-method, which is redundant in each user library, so that the user don`t have to think about it?

I thought it would be possible with templates+macros, but I haven't yet found a way to do this...

Another approach, I was thinking is directly call the constructor of any user class via dlsym and appropiate name mangling. (I know any namespace + class name from a config file) But I don`t think this a proper solution, especially a constructor call is not the same as a regular function call... but very interesting...


回答1:


I can't imagine a way to create this automatically without any coding per part of the user. I can imagine ways to simplify it, perhaps using a macro:

#define OBJECT_CREATOR(X) \
    extern "C" {          \
         BaseClass *UserXCreateInstance() {\
             return new X(); \
         }\
    }

And the user just need to put on his cpp file:

OBJECT_CREATOR(UserClass);



回答2:


I'll assume calling the user function via dlsym is not an absolute requirement.

What you want is easy to achieve by using CRTP. A constructor of a static helper object then registers relevant data in a central repository. It should go like this:

template <typename UserClass>
class BaseClass
{
  private:
    class UserObjectFactory
    {
      UserObjectFactory()
      {
        std::string myname = typeid(UserClass).name();
        CentralObjectFactory::instance()->register(this, myname);
      }
      BaseClass* XUserCreateInstance()
      {
        return new UserClass;
      }            
    };
    static UserObjectFactory factory; 
};

Users code is simple:

class MyClass : public BaseClass<MyClass>
{
  // whatever
};

Presumably, the CentralObjectFactory instance contains some kind of (multi)map from std::string to UserObjectFactory.

myname could be initialized to some uniquely generated string instead of typeid(UserClass).name(), in order to avoid collisions.

If all you need is a single object of each user's class, you can make UserObjectFactory create an instance of UserClass and register it instead.

   std::string myname = typeid(UserClass).name();
   CentralObjectRepository::instance()->register(XUserCreateInstance(), myname);

Does this design fulfil your needs?



来源:https://stackoverflow.com/questions/6581998/factory-pattern-in-c-generating-explicit-createinstance-method-automaticall

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!