如何创建宏以通过该类的实例访问任何类中的任何变量

问题描述 投票:0回答:1

我有三个班级:

Object- 保存一些数据。

ObjectFactory - 从注册表创建对象的单例。

Editor - 客户端可以在 GUI 中添加对象,这些对象存储在文本文件中,然后在程序启动时生成。

现在,客户要添加一个新类:

ENGINE_SPAWNABLE(Foo)
class Foo : public Object
{
    int ValueA;
    int ValueB;
};

现在,这个 Foo 类可以使用

SpawnObject()
函数生成,因为类之前的
ENGINE_SPAWANABLE
宏将类添加到 ObjectFactory 的注册表中:

Object* foo_instance = SpawnObject("Foo");
// Works with any class with ENGINE_SPAWNABLE() in .h file
// Note that Foo does not need to be #included into this file

但是,Foo 的“ValueA”变量不能用编辑器动态访问,例如:

Object* foo_instance = SpawnObject("Foo");
foo_instance->ValueA = 2;
// Cannot be done, we need #include Foo in the Editor.cpp
// Client must change code from "ValueA" to "ValueB" in order to set the ValueB value, it cannot be done from the Editor GUI.
// This is a problem: The client shouldn't change Editor code

编辑器应该能够知道 Foo 类的所有变量,将它们发送到 GUI,并能够根据 GUI 输入在实例到实例的基础上设置值,如下所示:

Object* foo_instance = SpawnObject("Foo");
// In Foo constructor we add the class pointer to registry
SetVariable(foo_instance, "ValueA", "2")
// We find the foo_instance pointer from registry and forcefully set the variable address.

// Imagine we read all these strings from a text file that the Editor GUI saves to
// Now client can change ValueB by changing the string from Editor GUI
// We'd have only two lines of code that'd work with any class and any variable
// Doesn't need to be safe, we can do safety checks before writing into text file

问题是,你是怎么做到的?我找不到任何关于宏的信息,该宏会创建可以使用单个指针访问的变量注册表,看起来像这样:

string variable_type, string variable_name, pointer_to_object, pointer_to_variable_address

从这个 struct/map/container/list/registry,我可以搜索一个对象和变量名的实例来更改任何变量,即使将添加具有新变量名的新类。

对查找有关此功能的信息有帮助吗?

c++ macros factory factory-pattern abstract-factory
1个回答
0
投票

你想做的事做不到,因为c++没有反射。至少不像你期望的那样工作。

std::ofsetoff
可以告诉你一些成员相对于指向实例的指针的偏移量。然而,这些信息并没有你想象的那么有用。

据我所知,您只能将

std::ofsetoff
添加到指向实例的指针,以检索 standard layout classes 所需的成员。其中一个要求是:

  • 层次结构中只有一个类具有非静态数据成员,并且

但是,您提到

Object
确实有成员。


如果你想多态地使用对象,简单的方法是使用一个公共基类作为接口。成员的名字通常不相关。如果您想自由地为成员指定任意名称,您仍然可以使用通用接口。类似的东西:

 struct base { 
     std::vector<int> get_properties() = 0;
     ~virtual base() {}
 };

 struct derived : base {
     int a = 0;
     int b = 42;
     std::vector<int> get_properties() { return  {a,b}; }
 };

如果你想让“属性”用名字装饰,你可以使用

std::vector<std::pair<std::string,int>> get_properties()
。如果属性是不同类型的,它会变得有点毛茸茸,但并非不可能。


宏不是解决方案。如果没有宏你做不到那么你也不能用宏来做(是的,有例外,

std::offsetof
是一个宏,但是你要找的对应“getmemberfromoffset
”不存在)。 

© www.soinside.com 2019 - 2024. All rights reserved.