防止在初始化之前使用函数,在C中使用类似构造函数

时间:2010-06-14 19:55:22

标签: c optimization function constructor initialization

这是我防止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中,我不知道如何去做。

欢迎任何其他想法!

5 个答案:

答案 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();

当程序启动时,这些静态变量将自动初始化并调用该函数。

重要说明:如果您需要在多个文件中进行此类初始化,则初始化的顺序是未定义的(通常对象的链接顺序决定了初始化的顺序 - 但没有规则。所以你这样做时一定要小心。