2

I would like to simulate the object oriented programming, so in C++, let's consider the following C code:

typedef struct tAnimal{
   char * name;
   int age;
}tAnimal;

typedef struct tAnimal2{
   char * name;
   int age;
   float size;
}tAnimal2;   

In C++ you can create a table of different objects which are inherited from the same class. I would like to do the same in C, let's consider the following code:

tAnimal ** tab;
tab = malloc(sizeof(tAnimal*)*2);
tab[0] = malloc(sizeof(tAnimal));
tab[1] = malloc(sizeof(tAnimal2));

Notice that the allocation works because malloc returns a void pointer, and C does not require casting. But I still have no access to the size field, because the type of tab elements is tAnimal after all.

Is there anyway to fix this?, I would like to stay away from void ** pointers.

Dima Chubarov
  • 16,199
  • 6
  • 40
  • 76
sorakun
  • 23
  • 1
  • 3
  • 1
    [**Here is a Project(a book) will help you to develop OO feature in C**](http://www.cs.rit.edu/~ats/books/ooc.pdf) – Grijesh Chauhan Jan 19 '13 at 15:25
  • 2
    "In C++ you can create a table of different objects which are inherited from the same class" is not true, only pointers to objects! If you used object you would slice them: http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c – fscan Jan 19 '13 at 15:31

3 Answers3

3

In C it's common to use a structure with a type-flag, and a union of the data:

typedef enum
{
    Animal1,
    Animal2
} AnimalType;

struct Animal
{
    AnimalType type;

    union
    {
        tAnimal  animal;
        tAnimal2 animal2;
    };
};

Now you can create an array of the Animal structure.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Yeah I would do it this way too. Note, however, that all the members in the array would be of the size of (tAnimal2 + enum). – Adrián Jan 19 '13 at 15:36
  • 2
    I think that's not what he wanted, from the sample code i think he wanted c++ style inheritance (eg: list of pointers to base object). – fscan Jan 19 '13 at 15:37
  • @fscan The OP writes that _"I would like to stay away from void ** pointers"_. In that case the only solution I can see is to use `union` as the structures differs in size otherwise and therefore can't be used in an array. – Some programmer dude Jan 19 '13 at 15:42
0

If you want to access the size field you have to cast your pointer to tAnimal2. Note, the same would be true for C++.

You can kind of simulate inheritance by embedding the first struct at the beginning of the second:

struct tAnimal{
   char * name;
   int age;
};

struct tAnimal2{
  struct tAnimal parent;

  float size;
};
fscan
  • 433
  • 2
  • 9
  • That's what I Would like to do actually, it's to simulate the inheritance, but the problem is still up. I am implementing an OO language that generate C code, and this is one of the C limits that I am faced, and still dealing with. Thank you very much for your help every one. – sorakun Jan 20 '13 at 18:40
0

In order to access the size field in tab[1] you can cast the pointer to a tAnimal2 pointer.

 tAnimal2* panimal2 = (tAnimal2*) tab[1];
 panimal2->size = 1.0;

However this practice is prone to data corruption since you will need a method to ensure that the element of the table you cast to tAnimal2 is indeed an instance of tAnimal2. You could use an additional type field as Joachim Pileborg suggests to check the type of the object.

Dima Chubarov
  • 16,199
  • 6
  • 40
  • 76