从其名称的字符串生成派生类实例。 (即反射)

发布于 2024-10-03 03:04:58 字数 752 浏览 8 评论 0原文

如果我有一个基类:

class Base 
{
public:
virtual void Test()=0;
};

并且在动态加载的模块(.so/.dll)中,我实现了一个从此类派生的类:

class SomethingFromBase : Base 
{
...
};

并且,一旦加载该库,用户就会要求创建 的实例SomethingFromBase (假设我们从 cin 获取名称。),并且,我们不了解 SomethingFromBase (即,无法仅执行 if(inputstr == "SomethingFrombase ") { ... } 有什么方法可以创建 SomethingFromBase 的实例吗?

我相当确定这在(标准)C++ 中是不可能的,但是,我总是希望 SO 能让我感到惊讶!

如果这个添加一些库是可能的,我仍然想知道它。 谢谢!

编辑:请参阅 cdhowie 的回答。实施该技术的指南: http://www.linuxjournal.com/article/3687?page=0,1 http://www.abstraction.net/ViewArticle.aspx?articleID=67

If I have a base class:

class Base 
{
public:
virtual void Test()=0;
};

and, in a dynamically loaded module (.so/.dll), I implemented a class derived from this:

class SomethingFromBase : Base 
{
...
};

and, the user, once this library is loaded, asks to create an instance of SomethingFromBase (let's say we get the name from cin.), and, we have no knowledge of SomethingFromBase (i.e, no way to just do if(inputstr == "SomethingFrombase") { ... } is there any way to create an instance of SomethingFromBase?

I'm fairly certain this is impossible in (standard) C++, but, I'm always hoping SO will surprise me!

If this is possible with the addition of some library, I'd still like to know about it.
Thanks!

Edit: See cdhowie's answer. Guides to implementing this technique:
http://www.linuxjournal.com/article/3687?page=0,1
http://www.abstraction.net/ViewArticle.aspx?articleID=67

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

静谧幽蓝 2024-10-10 03:04:58

通常,您需要插件库定义一些结构类型的全局变量来实现此目的,其中包含指向您可以调用的各种函数的指针。 (如设置、拆卸等)在设置函数期间,它们会回调到您的应用程序中的某个“注册”函数,在该函数中它们可以传入表示类名称的字符串和一个工厂函数指针,该指针将创建一个执行时的实例。

您将其存储在某个映射中,当用户输入字符串时,您会查看映射以查看是否注册了工厂函数。如果是这样,只需调用它即可。

所以这不是“真正的”反射,但您可以在某种程度上手动破解它。例如,参见 Pidgin,它允许规范可以在协议列表中提供许多条目的协议插件。

编辑: 这是一个实现某些内容的漂亮指南相似的。我是一个 C 级的人,所以我不能保证它真的很棒或者什么,但乍一看它看起来不错。我在 Linux 上用 C 语言做过类似的事情,基本方法效果很好。

You typically achieve this by required that plugin libraries define some global variable of a struct type that contains pointers to various functions you can call. (Like setup, teardown, etc.) During the setup function, they would call back into your application to some "register" function where they could pass in a string representing the name of the class, and a factory function pointer that will create an instance when executed.

You stash this away in some map, and when the user enters a string, you look at the map to see if there is a factory function registered. If so, just call it.

So this is not "true" reflection, but you can manually hack it to some degree. See, for example, Pidgin, which allows the specification of protocol plugins that may supply many entries in the protocol list.

EDIT: Here is a nifty guide to implementing something similar. I'm more of a C person, so I can't vouch for it being truly awesome or anything, but at first glance it looks good. I've done similar stuff in C on Linux, and the basic approach works pretty well.

善良天后 2024-10-10 03:04:58

使用映射存储类的对象,并以类名称为键。
需要以这种方式创建的所有类都需要从某个名为“Creatable”之类的基类派生
添加类的对象的代码需要与类的实现一起给出。

//Creatable.h
#define IMPLEMENT_CREATABLE( ClassName ) \
  ObjectMap::Instance().Add( string(ClassName), new ClassName );

//ObjectMap.h. This is a singleton
class ObjectMap
{
  ...........
  map<string, Creatable *> myMap;
  ...........
public:
  void Add( const string &className, Creatable * );
  Creatable * Get( const string &className );
};

//My Class.h
class MyClass : public Creatable
{
  ................
};

//My Class.cpp
IMPLEMENT_CREATABLE(MyClass);


//Client.cpp
string className;
cin>>className;
Creatable *anObject = ObjectMap::Instance().Get( className );

Have a map store the objects of the class, keyed by the class name.
All the classes that need to be created this way, need to be derived from some base class named something like "Creatable"
The code to add the object of the class need to be given with the implementation of class.

//Creatable.h
#define IMPLEMENT_CREATABLE( ClassName ) \
  ObjectMap::Instance().Add( string(ClassName), new ClassName );

//ObjectMap.h. This is a singleton
class ObjectMap
{
  ...........
  map<string, Creatable *> myMap;
  ...........
public:
  void Add( const string &className, Creatable * );
  Creatable * Get( const string &className );
};

//My Class.h
class MyClass : public Creatable
{
  ................
};

//My Class.cpp
IMPLEMENT_CREATABLE(MyClass);


//Client.cpp
string className;
cin>>className;
Creatable *anObject = ObjectMap::Instance().Get( className );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文