这是我防止funA,funB,funC等在初始化之前使用的方式
#define INIT_KEY 0xC0DE //any number except 0, is ok
static int initialized=0;
int Init()
{
//many init task
initialized=INIT_KEY;
}
int funA()
{
if (initialized!=INIT_KEY) return 1;
//..
}
int funB()
{
if (initialized!=INIT_KEY) return 1;
//..
}
int funC()
{
if (initialized!=INIT_KEY) return 1;
//..
}
这种方法的问题在于,如果在循环内调用其中一些函数 所以“if(initialized!= INIT_KEY)”再次被调用,并且再次调用,尽管没有必要。
这是一个很好的例子,为什么构造函数是有用的哈哈,如果它是一个对象,我会确定它在创建时,初始化被调用,但在C中,我不知道如何去做。
欢迎任何其他想法!
答案 0 :(得分:5)
使用指针指向功能。
在构造时,将函数指向函数 执行必要的初始化,然后更新函数指针以指向执行工作的实际函数。
我已经使用指向类中成员函数的指针数组来完成此操作。该类有一个内部整数,表示它所处对象的状态。整数用于下标成成员函数的指针数组...状态0执行init。状态1,做的工作,状态2将事情设置回状态1.
它非常干净。
答案 1 :(得分:4)
您可以使用某些预处理器宏来使用某种断言:
#ifdef DEBUG
# define ENSURE_INITIALIZED(obj) \
do { \
if (obj->initialized != INIT_CODE) { \
fprintf (stderr, "Object %p not initliaized (%s:%d)\n", obj, __FILE__, __LINE__); \
abort (); \
} \
} while (0)
#else
# define ENSURE_INITIALIZED(obj)
#endif
voif foo (Object *obj) {
ENSURE_INITIALIZED (obj);
}
这将检查初始化代码,但仅在调试版本中 - 在生产版本中,它将评估为no-op。
调用abort
将异常终止程序,通常会留下核心转储,或者在调试器中运行时中断程序。
答案 2 :(得分:1)
将您的函数放在一个结构中(使用函数指针来访问它们)。提供“构造”函数来创建该结构并在结构中分配正确的函数地址。与EvilTeach几乎相同的想法。
答案 3 :(得分:1)
您可以考虑不同的解决方案。在循环中,无论选择何种解决方案,都将始终执行一些额外的代码(最好在幕后)以防止执行这些函数。你可以在循环中跳过funX的执行,但这将是检查funX是否可以被执行的额外代码,放置方式不同。
由于通常在其他任务之前完成初始化,这是一个奇怪的问题,或者是错误的(你不应该称之为初始化)。
如果需要,函数可以自己调用初始化程序,如
if (!initialized) initialize();
始终是额外的代码,从那时起!!initialized将始终为false。
但避免一次又一次检查的方法是在游戏开始真实播放之前,在正确的位置明确调用初始化。 (否则不要将其称为初始化)。
如果它是一个对象,......你不需要对象。要“触发”构造函数,您必须创建对象(至少在许多OO语言中),例如new MyClass()
或“声明它”;这里调用“new”(这不是一个调用,但是对于这个语音,我们可以这样思考)或者“声明”被改为对一个显式初始化器的调用。你显然很简单
Object a;
// ...
a.method(); //or
Object *a = new Object();
// ...
a->method();
将是
init()
// ...
funA();
即使这个例子没有“匹配”你的“需要”,也应该明确一个显式的初始化程序并不是那么糟糕,而且OO语言真的不是“修复”这个问题所必需的。
您可以控制何时可以调用这些功能,因此您根本不需要检查;它发生在许多库中,它们需要先使用特殊的init函数才能使用它们,否则必须要有“奇怪的”行为。
答案 4 :(得分:1)
解决方案是像这样进行初始化(在每个文件中):
static int initResult = Init();
当程序启动时,这些静态变量将自动初始化并调用该函数。
重要说明:如果您需要在多个文件中进行此类初始化,则初始化的顺序是未定义的(通常对象的链接顺序决定了初始化的顺序 - 但没有规则。所以你这样做时一定要小心。