【问题标题】:C Casting between different struct-pointers during "simulated inheritance"“模拟继承”期间不同结构指针之间的 C 转换
【发布时间】:2012-03-05 11:02:34
【问题描述】:

嘿,我目前正在将 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;

我假设当我为“A UserTask”释放内存时,我足以释放 utask 并使用 deleteUserTask(utask)?如果我改为使用 deleteTask(task) 释放任务,我猜 UserTask 特定的内存将不会被释放。

我是 C++ 和 C 的新手,之前一直在使用 Java,动态内存分配仍然有点吓人...感谢您的帮助!

/帕特里克

【问题讨论】:

    标签: c inheritance casting struct free


    【解决方案1】:

    我认为在 C 中执行此操作的“正常”方法是将父结构内联而不是作为指针包含在内,即:

    struct Task{
      GenTask inhTask; 
    };
    

    这样,指向任务结构的指针可以向上转换为任务*。当然,“父”会与子实例一起自动释放。

    【讨论】:

    • 是的,我也看到了。我没有这样做的原因是 GenTask 结构也包含指针(在实现中),无论如何我必须深入研究它以释放该内存。但是,是的,我仍然看到将它作为指针有点多余。可能会改变这一点。但是,在“这样可以将指向任务结构的指针向上转换为任务 *”中,“任务”是什么意思。任何具有 GenTask 的结构?感谢回复
    • 我的意思是,如果您有一个 Task*,您可以透明地将其视为 GenTask*,而不必显式取消引用。如果 GenTask* 具有指向在删除结构时必须释放的内存的指针,那么您也必须对所有“子结构”执行此操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 2015-03-26
    • 1970-01-01
    • 2016-05-16
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多