C Приведение между различными структурами-указателями во время «симулированного наследования». - PullRequest
0 голосов
/ 05 марта 2012

Эй, я сейчас портирую программу на C ++ на C, и я упростил, я использую следующий код, когда симулирую наследование от классов 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;

Я предполагаю, что когда я освобождаю память для «UserTask», мне достаточно освободить utask и использовать deleteUserTask (utask)? Если вместо этого я освобождаю задачу с помощью deleteTask (задача), я думаю, что специальная память UserTask не будет освобождена.

Я новичок в C ++ и C, раньше использовал Java, и динамическое распределение памяти все еще немного страшно ... Спасибо за любую помощь!

/ Patrik

1 Ответ

2 голосов
/ 05 марта 2012

Я думаю, что «нормальный» способ сделать это в C состоит в том, чтобы включить встроенную родительскую структуру, а не в качестве указателя, т.е.

struct Task{
  GenTask inhTask; 
};

Таким образом, указатель на структуру задачи может быть приведен к Задаче *. И, конечно, «родитель» освобождается автоматически вместе с дочерним экземпляром.

...