给定这两种类型,我是否可以确定虚拟函数是否已被覆盖?

Given both types, can I determine if a virtual function have been overridden?

本文关键字:是否 函数 虚拟 覆盖 两种 类型      更新时间:2023-10-16

我正在设计一个由模块集合构建的系统。 基Module类具有一组虚拟函数,默认情况下这些函数不执行任何操作,但如果需要,可以在派生模块类中重写。

例如,其中一个函数是OnUpdate()。 目前,当更新发生时,我遍历所有模块并在每个模块上运行此功能。 当然,这会导致对任何不覆盖相关函数的模块进行许多"浪费"调用。

鉴于大多数模块不会覆盖大多数成员函数(并且分析表明这是我系统中的瓶颈(,我更愿意做的是跟踪哪些模块会覆盖成员函数并仅执行这些模块。 目前,我计划仅保留那些需要运行的模块指针的额外向量。

我的问题是收集此信息需要我检测模块是否已覆盖每个成员函数。 当我知道我正在使用的确切派生类型时,我可以对模块创建进行此分析,所以我认为这应该是可能的,但我期望工作的测试却没有。

下面是一些失败的简化检测代码:

template <typename T>
T & AddModule() {
static_assert(std::is_base_of<Module, T>,
"AddModule() can only take module types.");
// Create the new module and store it.
auto mod_ptr = std::make_shared<T>();
modules.push_back(mod_ptr);
// If the module has OnUpdate() track it!
// *** This test is not working! ***
if (&T::OnUpdate != &Module::OnUpdate) {
on_update_mods.push_back(mod_ptr);
}
// ...lots more tests here...
return *mod_ptr;
}

是否有其他方法可以处理此检测?

我也很高兴听到关于如何实现我的目标的替代想法。 我绝对希望模块编写者能够轻松地简单地实现任何指定的函数,并根据需要调用它们。

到目前为止,我想出的唯一其他选择是不要在模块基类中拥有虚函数,然后使用 SFINAE 在派生类中检测它们,然后将它们包装在 lambda 中并存储要运行的函子向量。 我认为这将起作用,但它会稍微慢一些(函子的间接性更多(并且更容易出错(现在如果您在成员函数名称中输入错误,覆盖关键字将抛出错误......

这个问题确实与这个问题相似,但提供的解决方案对我不起作用。 第一个选项要求在构造函数中单独标识所有工作成员函数,我可能正在使用数十个或更多,因此这很容易出错。 第二个选项让函数返回一个布尔值,但仅在运行时相关,并且在不需要它们时我无法运行它们。

我最终找到了解决这个问题的方法,让我得到了合理的加速。 具体来说,对于每个虚拟成员函数,我在基类中保留一个布尔值,指示该函数是否已被覆盖。 这些布尔值中的每一个都默认为 true,但成员函数的基本实现在执行时将其设置为 false(因为只有在函数未被覆盖的情况下才会运行(。

我定期扫描并更新我的向量,删除任何已被证明不存在的成员函数。

最终结果,~10% 加速,无需更改派生模块本身。 没有我希望的那么快,但考虑到这是一个科学软件,有些运行需要一个月,减少几天的休息时间肯定会有所帮助。

相关文章: