I had an idea about how to implement interfaces in C. The idea is really simple, but when searching for questions discussing this, I did not see it mentioned.
So, the "standard" inheritance emulation method in C is essentially
struct dad {
arm_t right_arm;
arm_t left_arm;
}
struct kid {
struct dad parent;
diaper_t diaper;
}
Which I think is ugly, because kid.parent.right_arm just makes less sense than kid.right_arm. There is another way apparently, if you don't mind using gcc-exclusive flags, which is something like
struct kid {
struct dad;
diaper_t diaper;
}
but this is not portable. What is portable, however, is
// file: dad.interface
arm_t right_arm;
arm_t left_arm;
// file: kid.h
struct kid {
#include dad.interface
diaper_t diaper;
}
For the purposes of this question, I'm not interested in suggestions for alternatives. My question is simply this: what, if anything, is wrong with this approach?
Since you pose the question in the context of inheritance, I suppose a more complete (and correct) example would be this:
arm_t right_arm;
arm_t left_arm;
struct dad {
#include "dad.interface"
};
struct kid {
#include "dad.interface"
diaper_t diaper;
};
There are several problems with this, among them:
It's not really inheritance -- it's merely two structures that happen to have matching initial members. struct kid has no other relationship with struct dad, and the former certainly does not inherit anything from the latter. From struct kids perspective, it's not even clear that a struct dad exists.
Although you did not use the term, it is common (albeit unwarranted) for people to assume that polymorphism goes hand-in-hand with inheritance. You don't get that with your approach. Despite sharing a common initial sequence of members, the two structure types are incompatible, and pointers to those types are incompatible, as that term is used by the standard. In particular, accessing a struct kid via a pointer of type struct dad * violates the strict aliasing rule, and therefore produces undefined behavior. (The same does not apply when struct kid embeds a struct dad as its first member.)
The approach has poor extensibility. For example, suppose you want to add struct son and struct daughter inheriting from struct kid. Now you have to pull out struct kid's members into its own separate header, too. I guess you could do that preemptively if you can predict which structure types anyone might ever want to inherit from, or if you just do it to every single structure type. Yikes, what a mess.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With