在声明函数时映射类的函数

发布于 2024-08-12 11:09:11 字数 555 浏览 8 评论 0 原文

我之前关于这个主题的问题得到了解答,并且我进行了一些测试,效果很好。 映射类的函数

我现在的问题是,是否有办法在声明函数时,能够将其注册在映射中,就像我在有关名称空间和类的问题中意识到的那样: 以某种方式在列表中注册我的类

命名空间和类是可以使用“static”关键字在映射中注册,这样,这些静态实例将在调用 main() 之前构建。

我可以用类函数来做到这一点吗?
因为当我在类声明中使用 static 关键字时,我无法像在类声明之外那样初始化成员(与上面第二个 url 中的命名空间和类一样)

我想我可以对构造函数内的所有成员进行硬编码并注册它们在地图中,但我想知道在我声明成员时是否有办法做到这一点,以便将来更容易

谢谢,

My previous question about this subject was answered and I got some tests working nice.
Map functions of a class

My question is now, if there is a way to while declaring the function, be able to register it in a map, like I realized in this question about namespaces and classes:
Somehow register my classes in a list

the namespaces and classes was fine to register in a map using the "static" keyword, with that, those static instances would be constructed before the main() be called.

Can I do that somehow with class functions?
because when I use static keyword inside a class declaration, I can't initialize the member as I can outside the class declaration(as with namespaces and classes in the second url above)

I guess I could hardcode all members inside the constructor and register them in a map, but I would like to know if there is a way to do that while I declare the members, to make it easier in the future

Thank you,
Joe

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

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

发布评论

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

评论(3

如梦初醒的夏天 2024-08-19 11:09:11

你这里有什么问题吗?

不幸的是,问题在于,在 C++ 中,函数不被视为一等成员。

哦,当然有那些工作得很好的函数指针,但是没有通用函数类型或类似的东西。

然而,有一些方法可以解决这个问题,我认为最简单的是命令模式。

在命令模式中,函数(操作)被抽象为一个对象。参数存储在对象中以供以后重用(例如 undoredo 命令),并且存在一个统一的接口来执行操作本身。

少说话,多代码:

class Command
{
public:
  virtual ~Command() {}

  virtual Command* clone() const = 0;

  virtual void execute() = 0;
};

简单?

class Foo {};

class FooCommand: public Command
{
public:
  void parameters(Foo& self, int a, std::string const& b);

  virtual FooCommand* clone() const;
  virtual void execute();

private:
  Foo* m_self;
  int m_a;
  std::string const* m_b;
};

现在,最棒的是我可以简单地将命令存储在地图中。

 // registration
 typedef boost::ptr_map<std::string, Command> commands_type;

 commands_type commands;
 commands.insert("foo", FooCommand());

 // get the command
 Foo foo;
 FooCommand* cFoo = dynamic_cast<FooCommand*>(commands["foo"].clone());
 if (cFoo != 0)
 {
   cFoo->parameters(foo, 2, "bar");
   cFoo->execute();
 }

该提案仍需要一些工作。

  • 传递参数非常烦人,因为它需要向下转换。
  • 我并不关心异常安全,但返回 auto_ptrshared_ptr 对于 clone 方法会更好
  • ...引入 const 和非 const Foo 参数并不容易。

然而,它比使用 void* 来存储映射中函数的指针更安全,因为您可以利用 RTTI 来检查类型是否正确。

另一方面,打印链接到特定对象的命令集合现在非常容易(如果每个对象都有一个映射),您还可以找到模拟虚拟方法等效果的方法。 ..

但我希望你意识到你实际上是在尝试实现反射,而且这并不容易......祝你好运!

What is your problem here ?

The problem is that, unfortunately, in C++ functions are not considered first class members.

Oh sure there are those pointers to functions that work pretty well, but there is no generic function type or anything like that.

There are however ways to work around this, the simplest I think being the Command pattern.

In the Command pattern a function (operation) is abstracted away in an object. The arguments are stored in the object for later reuse (for example undo or redo command) and a unified interface exists to perform the operation itself.

Less talk, more code:

class Command
{
public:
  virtual ~Command() {}

  virtual Command* clone() const = 0;

  virtual void execute() = 0;
};

Simple ?

class Foo {};

class FooCommand: public Command
{
public:
  void parameters(Foo& self, int a, std::string const& b);

  virtual FooCommand* clone() const;
  virtual void execute();

private:
  Foo* m_self;
  int m_a;
  std::string const* m_b;
};

Now, the sweet thing is that I can simply store my command in a map.

 // registration
 typedef boost::ptr_map<std::string, Command> commands_type;

 commands_type commands;
 commands.insert("foo", FooCommand());

 // get the command
 Foo foo;
 FooCommand* cFoo = dynamic_cast<FooCommand*>(commands["foo"].clone());
 if (cFoo != 0)
 {
   cFoo->parameters(foo, 2, "bar");
   cFoo->execute();
 }

This proposal would still require some work.

  • passing the parameters is quite annoying since it requires a down cast.
  • I did not concern myself with exception safety, but returning an auto_ptr or a shared_ptr would be better for the clone method...
  • the distinction between a const and non-const Foo argument is not that easy to introduce.

However it is safer than using a void* to store the pointers to function in you map since you have the advantage of RTTI to check whether or not the type is correct.

On the other hand, printing the collection of Commands linked to a particular object is incredibly easy now (if you have one map per object), you can also find ways to emulate the effect of virtual methods etc...

But I hope you realize that you are in fact trying to implement reflection, and it's not gonna be easy... good luck!

§普罗旺斯的薰衣草 2024-08-19 11:09:11

您可以使用预处理器来允许如下代码:

#include <iostream>

#include "Registration.h"

class myclass {
  public:
  myclass() { HANDLE_REGISTRATION(); }

  private:
  static void reg1()  { std::cout << "reg1" << std::endl; }
  static void reg2()  { std::cout << "reg2" << std::endl; }
  static void unreg() { std::cout << "ERROR!" << std::endl; }

  BEGIN_REGISTRATION();
    REGISTER(reg1);
    REGISTER(reg2);
  END_REGISTRATION();
};

int main()
{
  myclass obj;
  obj.callAllRegistered();

  return 0;
}

丑陋的预处理器黑客隐藏在 Registration.h 中:

#ifndef INCLUDED_REGISTRATION_H
#define INCLUDED_REGISTRATION_H

#include <string>
#include <map>

#define BEGIN_REGISTRATION() \
  std::map<std::string, void(*)()> reg; \
  void register_static(const std::string& name, void(*f)()) \
  { \
    reg[name] = f; \
  } \
  void registerAll() {

#define REGISTER(name) register_static(#name, name)

#define HANDLE_REGISTRATION() registerAll()

#define END_REGISTRATION() \
  } \
  public: \
  void callAllRegistered() { \
    std::map<std::string,void(*)()>::const_iterator it; \
    for (it = reg.begin(); it != reg.end(); ++it) \
      it->second(); \
  } \
  private: \
  typedef int unusedblahblahblah___

#endif

You could use the preprocessor to allow code such as the following:

#include <iostream>

#include "Registration.h"

class myclass {
  public:
  myclass() { HANDLE_REGISTRATION(); }

  private:
  static void reg1()  { std::cout << "reg1" << std::endl; }
  static void reg2()  { std::cout << "reg2" << std::endl; }
  static void unreg() { std::cout << "ERROR!" << std::endl; }

  BEGIN_REGISTRATION();
    REGISTER(reg1);
    REGISTER(reg2);
  END_REGISTRATION();
};

int main()
{
  myclass obj;
  obj.callAllRegistered();

  return 0;
}

The ugly preprocessor hacks are hidden away in Registration.h:

#ifndef INCLUDED_REGISTRATION_H
#define INCLUDED_REGISTRATION_H

#include <string>
#include <map>

#define BEGIN_REGISTRATION() \
  std::map<std::string, void(*)()> reg; \
  void register_static(const std::string& name, void(*f)()) \
  { \
    reg[name] = f; \
  } \
  void registerAll() {

#define REGISTER(name) register_static(#name, name)

#define HANDLE_REGISTRATION() registerAll()

#define END_REGISTRATION() \
  } \
  public: \
  void callAllRegistered() { \
    std::map<std::string,void(*)()>::const_iterator it; \
    for (it = reg.begin(); it != reg.end(); ++it) \
      it->second(); \
  } \
  private: \
  typedef int unusedblahblahblah___

#endif
残花月 2024-08-19 11:09:11

您正在寻求的是一种名为反射的原则。不幸的是,C/C++ 不提供此功能,并且在 C++ 对象中实现它会非常复杂(如果可能的话)。

如果需要此功能,我建议查看另一种支持此类元编程功能的语言。在其他一些语言中,做这件事是微不足道的。例如,在 Ruby 中,您可以说:

class Myclass
  def initialize
  end

  def a
  end

  def b
  end
end

x = Myclass.new
x.methods
=> ["inspect", "b", "clone", "taguri", "public_methods", "display", "instance_va
riable_defined?", "equal?", "freeze", "taguri=", "methods", "respond_to?", "dup"
, "instance_variables", "to_yaml_style", "__id__", "method", "eql?", "id", "sing
leton_methods", "send", "taint", "frozen?", "instance_variable_get", "__send__",
"instance_of?", "to_a", "type", "to_yaml_properties", "protected_methods", "obj
ect_id", "instance_eval", "==", "===", "instance_variable_set", "to_yaml", "kind
_of?", "extend", "to_s", "a", "hash", "class", "tainted?", "=~", "private_method
s", "nil?", "untaint", "is_a?"]

这将列出与该对象关联的所有成员函数(在本例中,其中许多是自动生成的)。对于实例变量等也可以这样做。许多其他语言都提供这些类型的功能。

如果此功能对您正在做的事情至关重要,那么我建议您重新检查您选择的编程语言,因为您似乎希望在比 C/C++ 通常设计的更高级别上工作。通过使用某种对象/类生成器模式,可能可以将此类事情硬塞到 C++ 中,但编写或使用生成的类并不是一件容易的事。

What you are seeking is a principle called Reflection. Unfortunately, C/C++ does not provide this functionality, and implementing it in a C++ object would prove very complicated (if it's even possible).

If this functionality is needed, I would suggest looking at another language that supports metaprogramming features like this. Doing this exact thing is trivial in some other languages. For example, in Ruby you could say:

class Myclass
  def initialize
  end

  def a
  end

  def b
  end
end

x = Myclass.new
x.methods
=> ["inspect", "b", "clone", "taguri", "public_methods", "display", "instance_va
riable_defined?", "equal?", "freeze", "taguri=", "methods", "respond_to?", "dup"
, "instance_variables", "to_yaml_style", "__id__", "method", "eql?", "id", "sing
leton_methods", "send", "taint", "frozen?", "instance_variable_get", "__send__",
"instance_of?", "to_a", "type", "to_yaml_properties", "protected_methods", "obj
ect_id", "instance_eval", "==", "===", "instance_variable_set", "to_yaml", "kind
_of?", "extend", "to_s", "a", "hash", "class", "tainted?", "=~", "private_method
s", "nil?", "untaint", "is_a?"]

This will list all of the member functions (many of them are automatically-generated in this case) associated with the object. The same can be done for instance variables, etc. Many other languages offer these types of features.

If this feature is critical to what you are doing, then I would recommend that you re-examine your choice of programming language as you seem to be wanting to work on a higher level than C/C++ are typically designed for. It may be possible to shoehorn this sort of thing into C++ by using some sort of object/class generator pattern but it would not be trivial to write or to use the resulting classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文