2010-06-14 2 views
3

에서이 있다는 것입니다이 방법으로 초기화초기화하기 전에 기능을 사용 방지, 생성자 같은 C

#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; 
//.. 
} 

전에 문제를 사용하기위한 .. 내가 funA, funB, FUNC 등을 방지하기 위해 얻는 방법 이러한 함수 중 일부가 루프 내에서 호출되는 경우 "if (initialized! = INIT_KEY)"가 다시 호출되며 필요하지는 않지만 다시 호출됩니다.

생성자가 유용 할 수있는 좋은 예입니다. 객체 인 경우 객체가 생성 될 때 초기화가 호출되지만 C에서는 초기화를 수행하는 방법을 모릅니다.

다른 아이디어는 환영합니다!

+0

그러나 각 If는 초기화 된 경로에 정확히 하나의 추가 기계 명령어 즉 단일 비교를 생성합니다. 오버 헤드가 그렇게 나쁠 것이라고는 생각하지 않습니다. – JeremyP

+0

당신은 그것을 '객체'로 만들 수 있습니다. 그냥 struct에 물건을 넣은 다음 각 함수에 구조체를 전달한 다음 Init에 할당하고, 초기화하고, 포인터를 반환하고, 하나의 소스 파일에 구조체 정의를 유지하여 포인터 불투명하고 멤버 변수 private 인 클래스와 같습니다. – Spudd86

답변

5

함수 포인터를 사용하십시오.

구성시, 필요한 초기화를 수행하는 함수 에서 함수를 지정한 다음 작업을 수행하는 실제 함수를 가리 키도록 함수 포인터를 업데이트하십시오.

클래스의 멤버 함수에 대한 포인터 배열을 사용하여이 작업을 수행했습니다. 이 클래스는 객체가 어떤 상태인지를 나타내는 내부 정수를가집니다. 정수는 멤버 함수에 대한 포인터 배열에 첨자하기 위해 사용됩니다 ... 상태 0은 init을 수행합니다. 상태 1, 작업을 수행하면 상태 2가 상태 1로 되돌아갑니다.

아주 잘 작동했습니다.

+0

나는 약간의 추한 코드를 상상해 보지만 다른 놀라운 아이디어가 없다면 시도해 보겠다. 올바른 대답이 될 수있다. –

+0

정확히 내가 좋아하는 아이디어. 당신도 기능을 할 수있는 첫 번째 호출에 대한 첫 번째 호출에 대한이 작업을 수행 할 수 있습니다 : O – Nyan

+0

mmmm 구현하려고했는데 somethng이 보이지 않거나 함수 포인터를 초기화해야하기 때문에 여기에 역설이 있습니다 .. –

1

구조체에 함수를 넣으십시오 (함수 포인터를 사용하여 구조체에 액세스하십시오). 해당 구조를 생성하고 구조에 올바른 함수 주소를 할당하는 "구조"기능을 제공하십시오. EvilTeach와 거의 동일한 아이디어.

+0

예. 같은 생각입니다. –

+0

글쎄요, 똑같은 것은 아닙니다. "구성 시간"이있는 경우 초기화 함수를 호출 할 필요가 없습니다. 올바른 주소로 함수 포인터를 초기화 할 수 있습니다. 함수 포인터를 포함하는 구조체를 사용하면 생성자를 사용하여 클래스를 모방하려고하는 것과 유사하게 보입니다. – Ioan

1

당신은 다른 해결책에 대해 생각할 수 있습니다. 루프에서는 선택한 솔루션과 상관없이 기능이 실행되지 못하도록 일부 여분의 코드가 항상 실행됩니다. funX의 실행을 루프에서 건너 뛸 수 있지만, funX를 실행하고 다르게 배치 할 수 있는지 확인하는 데는 추가 코드가 필요합니다.

일반적으로 다른 작업 전에 초기화가 수행되기 때문에 이상한 문제이거나 잘못된 이름입니다 (초기화라고해서는 안됩니다). 당신이 원하는 경우

이 기능은

if (!initialized) initialize(); 

항상 여분의 코드처럼, 스스로 이니셜 라이저를 호출 할 수 있습니다! 항상 다음부터 잘못된 것 초기화.

하지만 반복해서 확인하는 것을 피하는 방법은 게임이 실제 게임을 시작하기 전에 올바른 위치에서 초기화를 명시 적으로 호출하는 것입니다. (그렇지 않으면 초기화라고하지 마십시오.)

개체라면 ... 개체를 필요로하지 않습니다. 생성자를 "trig"하려면 적어도 new MyClass() 또는 "선언"과 같이 객체를 생성해야합니다 (많은 OO 언어에서). 여기에서는 "new"에 대한 호출 (호출이 아니지만이 연설을 위해 우리는 이런 식으로 생각할 수 있습니다) 또는 "선언"이 명시 적 초기화 자의 호출로 변경됩니다.귀하 분명히 간단한

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

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

것이 예, 그것은 명시 적으로 초기화 그렇게 대단히 나쁘지 않다과 OO 언어 정말 명확하지 않다 "일치"를 "필요"해야 않더라도

init() 
// ... 
funA(); 

이 문제를 "고칠"필요는 없습니다.

이러한 기능을 호출 할 수있는 시간을 제어 할 수 있으므로 전혀 점검 할 필요가 없습니다. 그것은 당신이 그들을 사용할 수 있기 전에 특수한 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); 
} 

:

4

당신은 몇 가지 전처리 매크로를 사용하는 주장의 어떤 종류를 사용할 수 있습니다.

abort을 호출하면 비정상적으로 프로그램이 종료되고 일반적으로 코어 덤프가 남아 있거나 디버거에서 실행될 때 프로그램이 중단됩니다.

1

해결책은 (각 파일에) 이런 식으로 초기화를하는 것입니다 : 프로그램이 시작하면, 그 정적 변수가 자동으로 초기화되며 함수가 호출됩니다

static int initResult = Init(); 

.

중요 참고 : 둘 이상의 파일 (일반적으로 객체의 연결 순서가 초기화의 순서가 지시 이러한 초기화를 할 필요가있는 경우 초기화의 순서는 정의되어 있지 않습니다 -하지만 더 규칙 없다 그에 대한). 이렇게 할 때 조심해야합니다.

+1

중요한 주를 위해 +1 –

+3

이것은 C에서 작동하지 않습니다 ... – Spudd86

+0

@ spudd86 - 당신 말이 맞아요. – INS

관련 문제