KernelPanic
KernelPanic

Reputation: 31

multilevel inheritance in c

when doing inheritance in pure C like this

typedef struct {
    char name[NAMESIZE];
    char sex;
} Person;

typedef struct {
    Person person;
    char job[JOBSIZE];
} Employee;

typedef struct {
    Person person;
    char booktitle[TITLESIZE];
} LiteraryCharacter;

I know it is okay to cast a instance of type "LiteraryCharacter" to type "Person", and use it as such. But is it also ok/safe to cast a instance of type "LiteraryCharacter" to type "Employee" and use it as such?

Upvotes: 2

Views: 182

Answers (3)

Mihai Stancu
Mihai Stancu

Reputation: 16117

Undefined behavior:

In your example you are casting to-from incompatible types which doesn't even compile because of the differences in the sizes of those two types. You can however cast to-from compatible (or even incompatible) pointer types and it will compile.

Casting to-from incompatible (or rather pseudo-compatible) types is undefined behavior, on some structures and compiler implementations it will work on others it won't.

Casting to compatible -- pointer types is safe as long as the compiler is taking care of the object structure / internal alignments / memory layout, etc. (there's an example below).

The "OK" part is debatable. Will it work? Yes because they have the same "in memory" layout and you are aware of that particular fact. But what happens when another programmer created that structure? You have to read its source to assess if it can be safely cast to another type.

Encapsulation and future proofing:

Also most encapsulation techniques will only expose an "opaque type" which you can use via pointers -- pass it along to functions implemented within the same library/package and they do all of the structure specific work. In the case of "opaque types" you only know that that structure exists, you don't know it's internal structure so you can't just change the pointer type you're using to access it because you can't be sure of the structure compatibility behind it.

The point of encapsulation is to allow modules to be developed individually. So when the original developer of this external module changes the structure in a future version it breaks compatibility with your code (which shouldn't be using it that way anyway).

Safer way to do this:

This is a non standard (yet pretty much ubiquitous) compiler feature of GCC.

typedef struct {
    char name[NAMESIZE];
    char sex;
} Person;

typedef struct {
    Person;
    char job[JOBSIZE];
} Employee;

typedef struct {
    Employee;
    char booktitle[TITLESIZE];
} LiteraryEmployeeCharacter;

LiteraryEmployeeCharacter* lec = malloc(sizeof(LiteraryEmployeeCharacter));
lec->name = "My character";
lec->sex = 'F';
lec->job = "Steward";
lec->booktitle = "A book";

By using unnamed fields you get access to name, sex and job as if they were defined in the LiteraryEmployeeCharacter structure.

By casting to a compatible pointer type the compiler knows the exact structure and position of every field and ca easily handle the structure correctly.

Upvotes: 0

user4815162342
user4815162342

Reputation: 155196

Such a cast is undefined behavior in standard C, although it will work with many compilers.

Even if it works on a compiler you are currently using, be aware that it might break in a future version of the compiler, or with a different compiler. The C standard allows the compiler to assume that pointers to different types don't point to the same memory - except for some well-documented exceptions, which include cast of LiteraryCharacter * to Person *. The code that casts LiteraryCharacter * to Employee * can and will break under a compiler that makes use of this assumption to generate efficient code.

It might be a good idea to explain why you think you need this cast in the first place. Its equivalent would be quite incorrect in C++, and generate a ClassCastException in Java. After all, LiteraryCharacter doesn't have the fields of Person, such as job.

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234785

That would be undefined behaviour. There is no such thing as inheritance in C.

You might get away with it if the structures had exactly the same layout but that would be very brittle code indeed.

Upvotes: 0

Related Questions