2012-03-20 4 views
3

'재미'가있는 경우 포인터 기능을 사용하여 C++ 멤버 함수를 C에 에뮬레이트하기로했습니다.포인터 함수를 사용하여 C 구조체의 멤버 함수를 에뮬레이트

obj.h :

#ifndef OBJ_H 
#define OBJ_H 

#include <stdlib.h> 
#include <stdio.h> 

struct Obj{ 
    struct pObjVar* pVar; 

    void (*read)(struct Obj*); 
    void (*set) (struct Obj*, int); 
}; 

struct Obj* newObj(); 
void deleteObj(struct Obj** obj); 

#endif 

obj.c :

#include "obj.h" 

void readValue(struct Obj* this_); 
void setValue (struct Obj* this_, int mValue_); 

struct pObjVar{ 
    int mValue; 
}; 

struct Obj* newObj(){ 
    struct Obj* tmp = (struct Obj*)  malloc(sizeof(struct Obj)); 
    tmp->pVar  = (struct pObjVar*) malloc(sizeof(struct pObjVar)); 

    tmp->pVar->mValue = 0; 
    tmp->read = readValue; 
    tmp->set = setValue; 

    return tmp; 
} 

void deleteObj(struct Obj **obj){ 
    free((*obj)->pVar); (*obj)->pVar = NULL; 
    free((*obj)); *obj = NULL; 
} 

void readValue(struct Obj *this_){ 
    printf("Value = %d\n",this_->pVar->mValue); 
} 

void setValue(struct Obj *this_, int mValue_){ 
    this_->pVar->mValue = mValue_; 
} 

의 main.c :

#include "obj.h" 

int main(void) 
{ 
    struct Obj* a = newObj(); 
    a->set(a, 10); 
    a->read(a); 
    deleteObj(&a); 

    return 0; 
} 

출력 :

>./a.out 
Value = 10  
다음은 간단한 코드

그러나이 작업을 수행 할 때 암시 적으로 this 포인터를 내 멤버 함수에 명시 적으로 전달하여 포인터 역할을 에뮬레이션해야한다고 생각했습니다. 이것은 잘 동작 합니다만, 모든 것이 이상하게 보일뿐입니다! 나는 개체를 전달하고 싶었다면

, 왜 멤버 함수와 같은 기능을 구현하는 것이? 내가 찾은 유일한 대답은 통합 인터페이스를 원하지만 다양한 구현이 필요한 경우 일 것입니다. (뭔가가 과 비슷한 ~ C++ 가상 함수?)

회원 기능을 에뮬레이션하는 다른 이유는 무엇입니까? 또한 명시 적으로 this_ 포인터를 전달할 수있는 방법이 있습니까?

편집 : 개체를 전달할 때 원본 코드에 문제가있었습니다. 실수로 read/set 함수를 사용하여 &a을 사용하고있었습니다. 포인터를 NULL 내부적으로 설정하려면 deleteObj에만 필요합니다.

+1

당신은 기능, 즉'의 Obj **'포인터의 _address_을 전달하고 있습니다. 함수 호출에서'&'를 건너 뛰십시오. –

+0

@ JoachimPileborg : 정확합니다.내 편집 – GradGuy

+0

을 보았습니다. 복잡한 접근 방식을 사용하는 유사한 접근법과 구조체에 대한 포인터 대신에 불투명 한 typedef'ed int 값을 사용하여 병합을 추가해야만했습니다. 말할 필요도없이 디버깅/유지 관리가 악몽이었습니다! – SirDarius

답변

3

그냥 다른 방법은 :

#define member(FUNC, ...) FUNC(this_, ## __VA_ARGS__) 
int reader(struct Obj *_this) { 
    member(read, a, b, c); 
    member(getch); 
    return 0; 
} 

이 인터페이스, 상속 및 수업 시간에 C에서 다음과 같이 구현 된 많은 C++ 기능을 구현하기 위해 사용될 수있다. Linux 커널에서 파일 작업은 다음과 같이 구현됩니다. 파일 구조는 기능에 대한 포인터를 저장하여 각 파일 시스템이 구조의 데이터에서 작동하는 자체 시스템 호출 핸들러를 저장할 수 있습니다.

1

아니, 거기 C.에 자동으로 표준 처리기를이 작업을 수행 할 수있는 방법입니다 변환을 할 충분한 능력이 없습니다.

이제 함수가 a->func(10)처럼 호출 된 것을 찾기위한 방법이있다. 이 함수는 단지 func(10)입니다. 비얀 스트로브 스트 룹은 C++을 설계하기 시작했을 때

, 그는 이것에 대한 특별한 전처리/컴파일러 Cfront을 썼다. 현실에서

는, C++ 정말 (비 가상) 함수에 대한 포인터를 저장하지 않습니다. 코드를 컴파일하는 동안 과 같은 것으로 a->set(10)을 변환합니다. 글을 쓰는

관련 문제