【问题标题】:Semi-inheritance in C: How does this snippet work?C 中的半继承:这个片段是如何工作的?
【发布时间】:2010-07-23 21:48:36
【问题描述】:

破解 C 中有限形式的多态性的一种方法是执行以下操作:

typedef struct {
    int x;
} base;

typedef struct {
    base super;
    int y;
} derived;

现在您可以将派生实例称为基础实例,具体取决于变量的转换方式,即:

derived my_derived;
my_derived.y = 10;
my_derived.super.x = 20;
//will print 10
printf("%d", (&my_derived)->y);
//will print 20
printf("%d", ((base*)(&my_derived) )->x);

所以我的问题是,这究竟是如何工作的?是因为当您将其转换为基础并引用变量时,您将 int 成员“x”引用为从“基础”结构开始的偏移量?这是我唯一能想到的,任何帮助将不胜感激。

非常感谢!

【问题讨论】:

    标签: c oop inheritance


    【解决方案1】:

    在结构中,数据元素之间或结构末尾可以有未命名的填充字节,但开头不能。因此,结构类型对象的第一个数据元素的地址保证与结构类型对象本身的地址相同。

    因此,在您的示例中,my_derived 的地址与my_derived.super 的地址相同。

    【讨论】:

      【解决方案2】:

      struct是编译器知道他的结构的字节区内存,也就是你在里面声明了什么变量。

      例如你可以声明一个结构体:

      struct st {
        int number;
      };
      
      struct st n;
      n.number = 10;
      printf("n=%i\n", n.number);
      

      但是你可以改变编译器的行为,例如在你的结构体上声明一个指向 char 的指针:

      char *c = (char*)&n;
      printf("char c=%c\n", c[0]);
      

      这是一个法律声明。然后你可以随时改变那个记忆区的结构。唯一重要的是你声明的结构的内存地址。

      在你的例子中,当声明派生结构时,程序会保留一个内存区域来分配派生结构,但是编译器看到这个区域的形式可以随时更改:

      struct derived my_derived;
      struct base *b = (struct base*)&my_derived;
      
      b->x = 20;
      my_derived.y = 10;
      printf("x=%i y=%i\n", my_derived.base.x, my_derived.y);
      

      在这种情况下 b 和 &my_derived 共享相同的内存区域,您只需更改编译器“查看”该区域的方式。

      “类型双关语”的使用是 C 中 oop 遗产模拟的基础,这是一种非 oop 编程语言。

      我在我的项目中使用这种技术:oop4c

      【讨论】:

        【解决方案3】:

        是不是因为当您将其转换为基数并引用变量时,您将 int 成员“x”作为从“基数”结构开始的偏移量引用?

        是的。这种技术有时被称为“类型双关语”。

        这是在 POSIX 标准库中使用的;例如,在 struct sockaddr 中。通常您将一个声明为 sockaddr_storage,将其作为 sockaddr 传递,然后根据其中实际存储的地址类型将其作为 sockaddr_in 或 _in6 进行操作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-03-05
          • 2021-12-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-17
          相关资源
          最近更新 更多