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

防止在初始化之前使用函数,构造函数如C,c,optimization,function,constructor,initialization,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() {

这就是我预防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执行初始化。状态1开始工作,状态2将事情恢复到状态1


它工作得非常干净。

将函数放入结构中(使用函数指针访问它们)。提供一个“构造”函数来创建该结构,并在结构中分配正确的函数地址。几乎与EvilTeach的想法相同。

您可以考虑不同的解决方案。在循环中,无论选择哪种解决方案,都会执行一些额外的代码(最好是在幕后),以防止执行函数。您可以在循环中跳过funX的执行,但检查funX是否可以执行,这将是额外的代码,放置方式不同

由于通常初始化是在其他任务之前完成的,所以这是一个奇怪的问题,或者是命名错误(您不应该称之为初始化)

如果需要,函数可以自己调用初始值设定项,如

if (!initialized) initialize();
总是有额外的代码,而且!从那时起,initialized将始终为false

但是避免反复检查的方法是在游戏真正开始之前,在正确的位置显式调用初始化。(否则不要称之为初始化)

如果它是一个物体。。。你不需要这个对象。要“触发”构造函数,您必须创建对象(至少在许多OO语言中是这样),例如,
newMyClass()
或“声明它”;在这里,对“new”的调用(这不是一个调用,但对于这个演讲,我们可以这样想)或“声明”被更改为对显式初始值设定项的调用。你看起来很简单

Object a;
// ...
a.method(); //or

Object *a = new Object();
// ...
a->method();
会是

init()
// ...
funA();
即使这个例子与您的“需求”不匹配,也应该清楚,显式初始值设定项并不是非常糟糕,OO语言确实不需要“修复”这个问题


您可以控制何时可以调用这些func,因此根本不需要检查;在许多库中都会发生这种情况,需要先调用特殊的init函数,然后才能使用它们,或者必须预料到“奇怪”的行为。

您可以使用一些预处理器宏来使用某种断言:

#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
将异常终止程序,通常会留下一个核心转储,或者在调试器中运行时中断程序。

解决方案是这样做初始化(在每个文件中):

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


重要注意事项:如果需要在多个文件中执行此类初始化,则初始化的顺序是未定义的(通常对象的链接顺序决定了初始化的顺序,但没有规则规定)。因此,在执行此操作时,您必须小心。

我喜欢这样做,我想象有一点丑陋的代码,但我会尝试,如果没有其他令人惊讶的想法,它可能是一个正确的答案,感谢这是我最喜欢的想法。你甚至可以做一个函数,第一次调用和第二次调用都是这样:OMMM我试图实现我没有看到什么东西,或者这里有一个悖论,因为我必须初始化函数指针..是的。在构造函数中,init是指向执行init_键的函数的指针。在INIT_KEY函数中,INIT指向函数的指针来执行func_a、func_b、func_cWell中的工作,但不完全相同。如果有“构造时间”,就不需要调用初始化函数;您可以使用正确的地址等初始化函数指针。使用包含函数指针的结构似乎类似于使用构造函数模拟类。但每个ifs在初始化路径中只生成一条额外的机器指令,即单个比较。我不认为开销会这么大。你可以把它变成一个“对象”,把东西放到一个结构中,然后把结构传递到每个函数中,然后让Init分配、初始化并返回一个指向它的指针,把结构定义保存在你的一个源文件中,这样指针是不透明的,就像一个带有私有成员变量的类。
static int initResult = Init();