2012-03-05 5 views
0

안녕하세요, 저는 C++ 프로그램을 C로 이식하고 있습니다. C에서 structs를 사용하여 C++ 클래스에서 상속을 시뮬레이션 할 때 다음 코드를 사용하고 있습니다.C "시뮬레이션 된 상속"동안 다른 구조체 포인터 사이에 캐스팅

typedef struct GenTask GenTask; 
typedef struct Task Task; 
typedef struct UserTask UserTask; 

struct GenTask{ 
    char name[MAXCHAR]; 
    boolean isUserTask; 
    int k; 
    void (*print)(Task*); 
}; 

GenTask* newGenTask(const char* n){ 
    GenTask* inhTask = (GenTask*)malloc(sizeof(GenTask)); 
    strncpy(inhTask->name, n, MAXCHAR); 
    inhTask->k = 1; 
    return inhTask; 
} 

struct Task{ 
    GenTask* inhTask; 
}; 

void printTask(Task* task){ 
    printf("\nThis is Task: %s",task->inhTask->name); 
} 

Task* newTask(const char* n){ 
    Task* task = (Task*)malloc(sizeof(Task)); 
    task->inhTask = newGenTask(n); 
    task->inhTask->isUserTask = false; 
    task->inhTask->print = printTask; 
    return task; 
} 

void deleteTask(Task* task){ 
    free(task->inhTask); 
    free(task); 
} 

struct UserTask{ 
    GenTask* inhTask; 
    int m; 
}; 

void printUserTask(Task* task){ 
    UserTask* ut = (UserTask*)task; 
    printf("\nThis is UserTask nbr: %d",ut->m); 
} 

UserTask* newUserTask(const char* n){ 
    UserTask *ut = (UserTask*)malloc(sizeof(UserTask)); 
    ut->inhTask = newGenTask(n); 
    ut->inhTask->isUserTask = true; 
    ut->inhTask->print = printUserTask; 
    ut->m=100; 
    return ut; 
} 

void deleteUserTask(UserTask* utask){ 
    free(utask->inhTask); 
    free(utask); 
} 

코드 실행을 시도했는데 예상대로 작동합니다 (또는 작동하기를 바랍니다).). 내 질문에, 만약 여분의 "UserTask-memory"가 아래와 같이 타입 캐스팅 후에 노출 될 위험이 있다면 그렇습니다.

Task* task = (Task*)newUserTask("A UserTask"); 

UserTask 포인터로 다시 캐스트 할 때 아무런 문제가없는 것처럼 보입니다.

UserTask* utask = (UserTask*)task; 

내가 생각하는 나는 "A UserTask"무료 utask 및 사용 deleteUserTask (utask)에, I suffies에 대한 메모리를 해제 할 때? 대신 deleteTask (task)를 사용하여 자유 태스크를 사용하면 UserTask 특정 메모리가 해제되지 않는다고 생각합니다.

저는 C++과 C 모두에게 새로운 기능을 제공합니다. 이전에는 Java를 사용했고 동적 메모리 할당은 여전히 ​​약간 무서웠습니다 ... 어떤 도움을 주셔서 감사합니다!

/패트릭

답변

2

나는 C에서이 작업을 수행 할 수있는 '정상적인'방법 즉, 포인터로 부모 구조체 인라인을 포함하지 생각 :

struct Task{ 
    GenTask inhTask; 
}; 

그런 식으로 작업에 대한 포인터 구조체는 Task *에 캐스트 될 수 있습니다. 물론 '부모'는 자식 인스턴스와 함께 자동으로 해제됩니다.

+0

예 나는 그것을 또한 보았다. 내가 그렇게하지 않은 이유는 GenTask-struct가 (구현에서) 포인터를 포함하고 있기 때문에 어떻게 든 그 메모리를 해제해야만합니다. 하지만 그래, 나는 여전히 포인터로 사용하는 것이 다소 희박하다는 것을 알 수있다. 그걸 바꿀 수도 있어요. 하지만 "작업 구조체에 대한 포인터가 작업 *에 캐스트 될 수 있습니다"라는 의미에서 "작업"에 의해 명시 적으로 의미하는 것은 무엇입니까? GenTask가있는 구조체는 무엇입니까? 답장을 보내 주셔서 감사합니다 –

+0

만약 당신이 Task *를 가지고 있다면, 명시 적으로 역 참조하는 대신 투명하게 GenTask *로 취급 할 수 있습니다. GenTask *에 구조체를 삭제할 때 해제해야하는 메모리 포인터가 있으면 모든 '하위 구조체'에 대해서도이를 수행해야합니다. –