如果我有一个头文件foo.h和一个源文件foo.cpp,并且foo.cpp包含以下内容:
#ifdef WIN32
class asdf {
asdf() { startup_code(); }
~asdf() { cleanup_code(); }
};
asdf __STARTUP_HANDLE__
#else
//unix does not require startup or cleanup code in this case
#endif
但是foo.h没有定义类asdf,比如我有一个应用程序bar.cpp:
#include "foo.h"
//link in foo.lib, foo.dll, foo.so, etc
int main() {
//do stuff
return 0;
}
如果bar.cpp是在WIN32平台上编译的,那么asdf()和~asdf()会在适当的时间(分别在main()之前和程序退出时)调用,即使类asdf没有在foo.h,但通过foo.cpp链接?
答案 0 :(得分:5)
是的 - 但要非常小心。初始化静态对象(如asdf
对象)的顺序未定义。因此,如果任何其他对象试图在main()
之前引用您的对象,则它是未定义的行为。
此外,__STARTUP_HANDLE__
不是有效的标识符。任何标识符(甚至是宏)都不允许使用双下划线,也不允许使用单下划线后跟大写字母。
答案 1 :(得分:1)
如果没有损坏,请不要修理它。请注意静态初始化顺序问题,正如其他答案所说。但你真的应该修复那个保留的标识符。
__STARTUP_HANDLE__
的工作方式类似于运行时库,运行时库使用这样的名称,但它不是运行时库的一部分,因此不允许使用该名称。
#ifdef WIN32
namespace { // anonymous namespace - no outside access
class asdf {
asdf() { startup_code(); }
~asdf() { cleanup_code(); }
} x; // to create an instance
}
答案 2 :(得分:0)
只要对象(foo.o)本身链接到可执行文件中,这将起作用(假设静态初始化顺序fiasco没有击中你)。但是,如果你从库(foo.lib)中提取它,除非你明确地将对象标记为“活动对象”,否则它将不会,但我不记得如何在MSVC中这样做。
答案 3 :(得分:0)
在Windows上,使用DLL,您可以使用将在加载时调用的函数DllMain
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
return TRUE;
}