我正在构建一个c ++库,我需要为我的程序(和其他默认资源对象)初始化一个openGL上下文。在main之前调用的代码块中“隐藏初始化代码”是不错的做法(考虑现代c ++语义)?我不能使用静态变量,因为我需要按特定顺序初始化事物! (我无法在openGLm或SDL之前初始化纹理!)
这是我的代码:
#include <stdio.h>
#ifdef _MSC_VER // For msvc / msvc++ 2015
#define CCALL __cdecl
#pragma section(".CRT$XCU",read)
#define INITIALIZER(f) \
static void __cdecl f(void); \
__declspec(allocate(".CRT$XCU")) void (__cdecl*f##_)(void) = f; \
static void __cdecl f(void)
#elif defined(__GNUC__) for gcc / g++
#define CCALL
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
static void CCALL finalize(void)
{
/* Some king of delete / dispose here : like SDL_Quit, ... */
}
INITIALIZER(initialize)
{
/*
HERE IS THE STARTUP CODE ...
*/
}
答案 0 :(得分:3)
在main之前调用的代码块中“隐藏初始化代码”是不错的做法(考虑现代c ++语义)?
因为无法保证全局静态对象的初始化顺序,所以我认为这种做法一般都不好。另一个原因 - 为此类代码提供诊断并非易事,并且会产生人为问题,而不使用此方法可以轻松避免这些问题。有一些例外,但它们很少见,绝对没有多少人认为这是一种好的做法。
答案 1 :(得分:2)
考虑现代c ++语义,以及隐藏Init是不错的做法。代码&#34;在main之前调用的代码块?
在main
之前运行任何内容的唯一方法是在静态对象的构造函数中执行此操作。
我不能使用静态变量
你已经没有选择了。没有办法达到你在标准c ++中所要求的。
要回答一个问题,那就是良好的做法......这是基于意见的,但我会说,如果图书馆在明确之前对某些内容进行初始化,我通常会认为这是不好的告诉它初始化。这将阻止库的用户控制库相对于其他库的初始化顺序。当您的库依赖于SDL等其他库时,这一点尤其重要。
答案 2 :(得分:2)
标准第3.6.2节说明在main
的第一个语句之前可以初始化非本地静态变量 :
它是实现定义的动态初始化 具有静态存储持续时间的非局部变量在之前完成 主要的第一个声明。
因此,它并未表示在main
的第一个语句之前必须初始化。在C ++中,没有办法强制执行约束,即在调用main()
之前将对任何内容进行初始化,除了在与main相同的编译单元中定义的静态变量。
最佳解决方案只是将您的资源管理纳入main
本身:
int main()
{
// Load resources (housekeeping code)
// Do real work (applicative code)
// Release resources (housekeeping code)
}
如果您想将申请代码与管家代码分开,常用的方法是使用inversion of control(有时通过template method pattern):
main
负责执行内务处理以及调用用户代码或应用程序代码功能或方法。以下举例说明:
// The function below is expected to exist by the framework
// It must be implemented by the user
int userMain()
{
// Implement user-code here
}
// The code below is implemented by the framework
// It expects the user to have implemented a function userMain
int main()
{
FrameWorkData theFrameWorkData;
// The framework performs its initialization house-keeping here
theFrameWorkData.initialize();
// The framework invokes the user-code (inversion of control)
userMain();
// The framework performs its clean-up house-keeping here
theFrameWorkData.cleanup();
}