C inheritance through punning type, without containment?

I am in a position where I need to get some object-oriented functions that work in C, in particular inheritance. Fortunately, there are some good references to stack overflows, especially Half Inheritance C: How does this snippet work? and the Object orientation in the C . The idea is to contain an instance of the base class inside the derived class and output it like this:

struct base {
    int x;
    int y;
};

struct derived {
    struct base super;
    int z;
};

struct derived d;
d.super.x = 1;
d.super.y = 2;
d.z = 3;
struct base b = (struct base *)&d;

This is great, but it gets cumbersome with deep inheritance trees - I will have chains of 5-6 classes, and I really would not want to name a derivative. all the time. I was hoping that I could lead to the structure of the first n elements, for example:

struct base {
    int x;
    int y;
};

struct derived {
    int x;
    int y;
    int z;
};

struct derived d;
d.x = 1;
d.y = 2;
d.z = 3;
struct base b = (struct base *)&d;

C, Visual Studio 2012, , , C . -, , ? , .

+4
3

, , , , , , , . C89 Common Initial Sequence , , :

struct s1 {int x; int y; ... other stuff... };
struct s2 {int x; int y; ... other stuff... };
union u { struct s1 v1; struct s2 v2; };

struct s1* , a union u* malloc'ed union u* , struct s2*, struct s1* struct s2* , v1 v2. , , Common Initial Sequence.

, , , , , ( , , ), , , struct s1* struct s2*, union u, , . , , gcc , struct s1* struct s2*.

+3

struct - , .

-1

Using pointers, you can always create references to base classes at any level of the hierarchy. And if you use some kind of description of the inheritance structure, you can generate both class definitions and factory functions needed as a build step.

#include <stdio.h>
#include <stdlib.h>

struct foo_class {
  int a;
  int b;
};

struct bar_class {
  struct foo_class foo;
  struct foo_class* base;

  int c;
  int d;
};

struct gazonk_class {
  struct bar_class bar;
  struct bar_class* base;

  struct foo_class* Foo;

  int e;
  int f;
};

struct gazonk_class* gazonk_factory() {
  struct gazonk_class* new_instance = malloc(sizeof(struct gazonk_class));

  new_instance->bar.base = &new_instance->bar.foo;
  new_instance->base = &new_instance->bar;
  new_instance->Foo = &new_instance->bar.foo;

  return new_instance;
}

int main(int argc, char* argv[]) {
  struct gazonk_class* object = gazonk_factory();

  object->Foo->a = 1;
  object->Foo->b = 2;

  object->base->c = 3;
  object->base->d = 4;

  object->e = 5;
  object->f = 6;

  fprintf(stdout, "%d %d %d %d %d %d\n",
      object->base->base->a,
      object->base->base->b,
      object->base->c,
      object->base->d,
      object->e,
      object->f);

  return 0;
}

In this example, you can use pointers baseto go back or directly reference the base class.

-one
source

All Articles