问题描述
我想用类名和方法、唯一标识符和指向方法的指针填充映射.
I want to fill a map with class name and method, a unique identifier and a pointer to the method.
如果方法是静态的,那么一个简单的指针就足够了,问题很简单,但我想动态创建对象,所以我需要存储一个指向类的指针和方法的偏移量,我不知道这是否有效(如果偏移量总是相同等).
If the method is static then a simple pointer is enough and the problem is simple, but I want to dynamically create the object so I need to store a pointer to class and an offset for the method and I don't know if this works (if the offset is always the same etc).
问题在于 C++ 缺乏反射,在解释性语言中,有反射的等效代码应该是这样的(PHP 中的例子):
The problem is that C++ lacks reflection, the equivalent code in a interpreted language with reflection should look like this (example in PHP):
PS:是的,我正在尝试用 C++ 制作一个(网络)MVC 前端控制器.我知道我知道为什么不使用 PHP、Ruby、Python(在此处插入您最喜欢的网络语言)等?我只想要 C++.
PS: Yes I'm trying to make a (web) MVC front controller in C++. I know I know why don't use PHP, Ruby, Python (insert your favorite web language here) etc?, I just want C++.
推荐答案
我在上几个小时写了这些东西,并将它添加到我的有用东西集合中.最困难的是处理工厂函数,如果你想创建的类型没有任何关系.为此,我使用了 boost::variant
.你必须给它一组你想要使用的类型.然后它将跟踪变体中当前的活动"类型是什么.(boost::variant 是所谓的歧视联合).第二个问题是如何存储函数指针.问题是指向A
成员的指针不能存储到指向B
成员的指针.这些类型是不兼容的.为了解决这个问题,我将函数指针存储在一个重载其 operator()
并采用 boost::variant:
I wrote that stuff last hours, and added it to my collection of useful stuff. The most difficult thing is to cope with the factory function, if the types you want to create are not related in any way. I used a boost::variant
for this. You have to give it a set of types you ever want to use. Then it will keep track what is the current "active" type in the variant. (boost::variant is a so-called discriminated union). The second problem is how you store your function pointers. The problem is that a pointer to a member of A
can't be stored to a pointer to a member of B
. Those types are incompatible. To solve this, i store the function pointers in an object that overloads its operator()
and takes a boost::variant:
当然,所有类型的函数都必须具有相同的返回类型.否则整个游戏就没有什么意义了.现在代码:
Of course, all your types' functions have to have the same return type. Otherwise the whole game would only make little sense. Now the code:
它使用了来自 boost 预处理器、函数类型和绑定库的非常有趣的技术.可能循环复杂,但如果您获得该代码中的键,就不再需要掌握了.如果你想改变参数数量,你只需要调整 variant_call_type:
It uses pretty fun techniques from boost preprocessor, function types and bind library. Might loop complicated, but if you get the keys in that code, it's not much to grasp anymore. If you want to change the parameter count, you just have to tweak variant_call_type:
现在您可以调用带有 int 的成员函数.以下是呼叫方的外观:
Now you can call member functions that take an int. Here is how the call side would look:
玩得开心!
如果你现在说以上太复杂了,我不得不同意你的看法.它很很复杂,因为C++不是真正为这种动态使用而生的.如果可以在要创建的每个对象中对方法进行分组和实现,则可以使用纯虚函数.或者,您可以在默认实现中抛出一些异常(如 std::runtime_error),因此派生类不需要实现所有内容:
If you now say the above is too complicated, i have to agree with you. It is complicated because C++ is not really made for such dynamic use. If you can have your methods grouped and implemented in each object you want create, you can use pure virtual functions. Alternatively, you could throw some exception (like std::runtime_error) in the default implementation, so derived classes do not need to implement everything:
对于创建对象,通常的工厂就可以
For creating objects, a usual factory will do
映射可以由映射 ID 到一对类和函数名称(与上面相同)的映射以及映射到 boost::function 的映射组成:
The map could be composed by a map mapping IDs to a pair of class and function name (the same like above), and a map mapping that to a boost::function:
调用函数的方式如下:
当然,使用这种方法,您会失去灵活性和(可能尚未分析)效率,但您可以大大简化您的设计.
Of course, with this approach, you loose flexibility and (possibly, haven't profiled) efficiency, but you greatly simplify your design.
这篇关于在 C++ 中动态创建和调用类方法的最简单方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!