【问题标题】:How to extend a function如何扩展功能
【发布时间】:2018-02-12 00:14:48
【问题描述】:

在现代 C++ 中有没有办法“扩展”一个函数? 也许这个伪代码可以解释我想要什么:

extendable void foo()
{
   doSomething();
}

extend foo()
{
   moo();
}

编译函数foo()时应该这样做:

foo()
{
    doSomething();
    moo();
}

我想我可以通过将我想要在foo() 中拥有的每个函数存储在函数指针的 std::vector 中来做到这一点,foo() 将循环通过向量并运行所有函数。

但是,我需要在编译时执行此操作,因此我无法运行 vector.push_back()

我尝试在#define 指令的帮助下执行此操作,但没有找到解决方案。

提前感谢您的任何回答。

编辑:我的实际问题

我想实现某种实体组件系统,每个组件都有一个列表。每个实体都有一个 ID,指向组件列表中的列表元素。 因为我不想重复创建新类型组件的步骤,所以我想创建一个#define-directive 来为我将创建的每个新组件自动执行此操作。

主要问题是在创建新实体时向每个组件向量添加一个元素。 这是我想要工作的代码:

#define addComponent(name)                                          \
    struct name;                                                    \
private:                                                            \
    std::vector<name> name ## vector;                               \
public:                                                             \
    extend addEntity()                                              \
    {                                                               \
        struct name a;                                              \
        name ## vector.push_back(a);                                \
    }                                                               \
    void set ## name(const int & ID, name newName)                  \
    {                                                               \
        name ## vector[ID] = newName;                               \
    }                                                               \
    name get ## name(const int & ID)                                \
    {                                                               \
        return name ## vector[ID];                                  \
    }

class Component
{
public:
    Component();
    ~Component();

    extendable void addEntity(int * ID);

    addComponent(position)
    struct position
    {
        float x, y, z;
    }
};

【问题讨论】:

  • 这被称为“虚拟方法”。而且它不是“现代的”,但它自 C++ 诞生以来就存在。
  • 让我们后退一步 - 为什么需要这个?
  • 这似乎是XY problem
  • @DariusDuesentrieb:请编辑您的问题以激发更多动力,并解释为什么您想要做这些事情以及为什么样的程序。
  • 你的宏显然不能也不能工作。那么你是如何考虑解决你的问题的(我仍然觉得很不清楚,即使在编辑之后)?

标签: c++ function oop


【解决方案1】:

您没有充分解释您的想法和原因(即使在您编辑之后)。对于成员函数,确实可以阅读更多关于vtables(实现dynamic dispatch 的常用方法)的信息。

但请注意,函数可以是值(特别感谢 lambda expressionsstd::function)。

然后,您可以使用std::dequeue 声明一个函数的双端队列todoque(它可以是static 变量或某个class 的字段等...)

 std::deque<std::function<void(void)>> todoque;

并扩展它,也许使用 lambda,

 todoque.push_back([](void) { moo(); };

并用

初始化它
  todoque{[](void){doSomething()}};

然后编码

 void foo() {
   for (auto f : todoque) f();
 }

我希望你明白了。

顺便说一句,在上面的示例中,可能不需要 lambda,您可能只需要编码 todoque.push_back(moo)

顺便说一句,我推荐阅读SICP(不是关于 C++,而是关于一种称为 Scheme 的函数式编程语言),它是一本出色的(可免费下载)编程入门。

我想我可以通过将我想在 foo() 中拥有的每个函数存储在函数指针的 std::vector 中来做到这一点

不,甚至更好,将其设为 std::vector&lt;std::function&lt;void(void)&gt;&gt; 并使用 lambda 表达式。

但是,我需要在编译时执行此操作,因此无法运行 vector.push_back()

为什么不呢?它可能发生在某些静态数据的构造函数中。

也许您的总体目标(您没有解释)也可以通过涉及JIT compiling 的运行时元编程技术和在运行时生成代码来实现。您可以使用 libgccjitLLVM 之类的库;您还可以在某个临时文件中发出 C++ 代码,将其编译为插件,然后 dlopen 该插件。另见this

关于您编辑的实体-组件-系统目标,您是否考虑过编写一些专门的 C++ 代码生成器(或预处理器),以适应您的构建自动化系统的规则(例如 makeninja 等...)在构建时明智地触发? Qt moc 可能是鼓舞人心的。还可以考虑使用一些通用预处理器,例如 m4gpp

【讨论】:

  • 如果我无法使用预处理器指令找到解决方案,它可能是我需要的专用代码生成器。
【解决方案2】:

我可以扩展功能吗?

没有。

你所描述的是不可能的。任何机制都不支持让编译器生成一个函数,该函数将调用 foo() 在扩展之前调用的函数。

虚拟方法无法解决问题,因为它们提供的只是Polymorphism(希腊语中的许多形式)。

【讨论】:

  • 我看不出虚拟方法在任何方面与问题描述的内容相比如何。
  • 但是虚函数必须是成员函数,也就是应用于对象的方法。另请阅读vtables
  • 你不能用virtual 扩展函数。您可以覆盖它们,仅此而已。
  • 根据上下文,虚函数可以解决他的问题——但我们还不知道他的问题是什么。让我们希望他澄清一下。
猜你喜欢
  • 2015-08-13
  • 2018-09-27
  • 2021-08-23
  • 2020-02-05
  • 2019-06-23
  • 2020-07-02
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
相关资源
最近更新 更多