目标是允许头文件“注册”一个初始化函数,这样 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/