c++ - 在 header 中排队调用

标签 c++ module extern

目标是允许头文件“注册”一个初始化函数,这样 main 就可以迭代这些函数并调用它们。我偶然发现了一个使用 __attribute__ 的解决方案,但它似乎仅适用于 GCC ( https://stackoverflow.com/a/37082249/7867841)。

// header1.h
void myInitializer(){}
REGISTER_THIS(&myInitializer);

// header2.h
void myInitializer2(){}
REGISTER_THIS(&myInitializer2);

// main.cpp
...
for_each_registered_ptr(){ call_ptr(); } // calls myInitializer and myInitializer2
...

是否有通用的解决方案?如果更容易实现,可以将函数与类或类型进行切换。

最佳答案

您可以滥用 static 函数局部变量来执行此操作,避免静态初始化顺序失败。

init.h 中,我们有这个:

#ifndef INIT_H
#define INIT_H

#include <vector>

// Can be changed to std::function<...> or whatever you need.
typedef void (*init_fn)();

// Returns int so it can easily be used in a variable initializer.
int register_initializer(init_fn fn);
std::vector<init_fn> & get_initializers();

#endif

然后,在init.cpp中:

#include "init.h"

int register_initializer(init_fn fn)
{
    get_initializers().push_back(fn);

    return 0;
}

std::vector<init_fn> & get_initializers()
{
    static std::vector<init_fn> ip;

    return ip;
}

一些注意事项,在我们继续其余部分之前:

  • static 本地只初始化一次,即第一次调用函数时。
  • “全局” vector 有点泄露。除非您向该 vector 中添加数万个条目,否则这不太可能成为问题。你总是可以 get_initializers().clear() 在使用后清空它。

我们会像这样在 a.cpp 中使用它:

#include <iostream>

#include "init.h"

static void a_init() { std::cout << "a_init()\n"; }

static auto dummy = register_initializer(a_init);

最后,我们有了(相当简单的)main.cpp:

#include "init.h"

int main() {
    for (auto fn : get_initializers()) {
        fn();
    }

    return 0;
}

关于c++ - 在 header 中排队调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43415695/

相关文章:

c++ - 获取进程主线程的句柄

python - 如果我正在制作 pip 模块,需要上传或添加哪些文件到 git 存储库

c - Microsoft Visual Studio 中的外部链接问题

c - 带有函数名称的 extern 关键字

c++ - 预增量运算符的行为

c++ - std::function 性能与模板相比

c++ - 三角形三角形重叠(但不是边缘)

python - 得到警告 “TimeSeries broadcasting along DataFrame index by default is deprecated”

Ruby module_function,调用模块的私有(private)方法,在模块的类方法样式中调用显示错误