【问题标题】:Struct inheritance in C. Accessing members in parent struct after type castingC中的结构继承。类型转换后访问父结构中的成员
【发布时间】:2020-11-16 08:16:45
【问题描述】:

在代码中,child 被强制转换为类型 Parent,并传递给 parentMovechild 没有成员 xyparentMove 如何访问child.parent.xchild.parent.y?类型转换如何在这里工作?谢谢

#include <stdio.h>

typedef struct{
    int x, y;
    int (*move)();
}Parent;

typedef struct {
    Parent parent;
    int h, w;
}Child;

int parentMove(Parent* parent, int y, int x){
    parent->y+=y;
    parent->x+=x;
    printf("%d %d", parent->y, parent->x);
    return 1;
}

int main(void) {
    Parent parent = {.x = 2, .y = 1, .move = &parentMove};
    Child child = {.parent = parent, .h = 3, .w = 4};
    ((Parent*)(&child))->move((Parent*)&child, 10, 10);
    return 0;
}

【问题讨论】:

  • Is pointer to struct a pointer to its first member?&amp;child == &amp;child.parent,后者是Parent *,这就是演员阵容起作用的原因。
  • int (*move)();应该是int (*move)(Parent* parent, int y, int x);,是不是故意省略了?
  • @csavvy 我知道它有效,所以我故意省略了它。不过这是个坏习惯
  • @Austin AFIK 那是 UB。所以它不起作用。它只是表现得像它一样。

标签: c inheritance


【解决方案1】:

parentMove 如何访问 child.parent.x 和 child.parent.y?

它不知道子部分。将 Parent 对象声明为独立对象或 Child 的成员都没有关系,这两种情况都适用。

类型转换在这里如何工作?

很糟糕...如果您必须从调用方强制转换为基类,那么您已经错误地实现了继承。看起来Child 应该实现自己的move,它以Child* 作为参数,如果只是为了使其成为父级的包装器。

【讨论】:

    【解决方案2】:

    类型转换如何在这里工作?parentMove 如何访问 child.parent.x 和 child.parent.y?

    在子结构中,第一个成员是父结构,所以子结构的内部内存表示为--

    {
        {
            int x;         [ .. 4bytes .. ]
            int y;         [ .. 4bytes .. ]
            int *move();   [ .. 4bytes .. ]
        }
        int h;             [ .. 4bytes .. ]
        int w;             [ .. 4bytes .. ]
    }
    

    当您访问 parent.x 时,它只不过是从起始地址(即 &parent )访问前 4 个字节。同样访问 parent.y 意味着从起始地址偏移 4 个字节后访问 4 个字节。

    因此,当您将子结构的地址作为指向父结构的指针传递时,子地址实际上指向内部的有效父结构成员,从某种意义上说,从子地址访问前 4 个字节实际上是类似的 parent.x包含的父结构的其他成员可以正确访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-31
      • 2020-05-24
      • 1970-01-01
      • 2021-08-05
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 2023-03-22
      相关资源
      最近更新 更多