Inheritance vs Interface Polymorphism (C)
Doxygen docs for the C implementation
Loading...
Searching...
No Matches
C Implimentation.c
Go to the documentation of this file.
1// C Implimentation.c : This file contains the 'main' function. Program execution begins and ends there.
2//
3// C has no classes, so it has neither native inheritance-based polymorphism
4// nor native interface-based polymorphism. Both are reproduced below the
5// way C code conventionally simulates them: a struct holding a function
6// pointer (or table of function pointers) that stands in for a vtable.
7
8#include <stdio.h>
9
10// ---------------------------------------------------------------------------
11// Part 1: "Inheritance-based" polymorphism simulated with a base struct
12// whose first member is a function pointer, mimicking a single-method vtable.
13// ---------------------------------------------------------------------------
14
15/**
16 * @brief Base "class" simulated as a struct holding a speak function pointer.
17 */
18typedef struct Animal {
19 void (*speak)(struct Animal*); /**< Function pointer standing in for a vtable slot. */
21
22/**
23 * @brief speak() implementation for Dog.
24 * @param self Pointer to the Animal base within a Dog instance.
25 */
26void dogSpeak(Animal* self) {
27 (void)self;
28 printf("bark\n");
29}
30
31/**
32 * @brief speak() implementation for Cat.
33 * @param self Pointer to the Animal base within a Cat instance.
34 */
35void catSpeak(Animal* self) {
36 (void)self;
37 printf("meow\n");
38}
39
40/** @brief "Subclass" of Animal that barks. */
41typedef struct { Animal base; } Dog;
42/** @brief "Subclass" of Animal that meows. */
43typedef struct { Animal base; } Cat;
44
45/**
46 * @brief Initializes a Dog instance, wiring its vtable pointer to dogSpeak.
47 * @param d Pointer to the Dog instance to initialize.
48 */
49void Dog_init(Dog* d) { d->base.speak = dogSpeak; }
50
51/**
52 * @brief Initializes a Cat instance, wiring its vtable pointer to catSpeak.
53 * @param c Pointer to the Cat instance to initialize.
54 */
55void Cat_init(Cat* c) { c->base.speak = catSpeak; }
56
57/**
58 * @brief Dynamic Dispatch via manual function-pointer vtable.
59 * @param a Pointer to the Animal base whose speak function pointer is invoked.
60 */
61void makeSpeak(Animal* a) {
62 a->speak(a);
63}
64
65// ---------------------------------------------------------------------------
66// Part 2: "Inheritance with defaults" - a shared concrete function (sleep)
67// plus a per-instance function pointer (speak) standing in for the abstract
68// method that "subclasses" must fill in.
69// ---------------------------------------------------------------------------
70
71/**
72 * @brief Abstract base "class" combining shared state and an abstract
73 * speak function pointer.
74 */
75typedef struct AbstractAnimal {
76 int age; /**< Structural state isolated inside the struct footprint. */
77 void (*speak)(struct AbstractAnimal*); /**< Function pointer for the abstract method. */
79
80/**
81 * @brief A concrete default function shared by all "subclasses".
82 * @param aa Pointer to the AbstractAnimal base.
83 */
85 (void)aa;
86 printf("Zzz\n");
87}
88
89/**
90 * @brief speak() implementation for DogWithDefault.
91 * @param self Pointer to the AbstractAnimal base within a DogWithDefault instance.
92 */
94 (void)self;
95 printf("bark\n");
96}
97
98/** @brief Concrete AbstractAnimal "subclass" that implements speak(). */
100
101/**
102 * @brief Initializes a DogWithDefault instance.
103 * @param d Pointer to the DogWithDefault instance to initialize.
104 */
109
110/**
111 * @brief Dynamic Dispatch using abstract parent pointer.
112 * @param aa Pointer to the AbstractAnimal base; sleep() is a shared,
113 * non-overridden default function.
114 */
116 Animal_sleep(aa);
117}
118
119// ---------------------------------------------------------------------------
120// Part 3: "Interface-based" polymorphism simulated with a struct that holds
121// only a function pointer, i.e. a contract with no shared state or code.
122// ---------------------------------------------------------------------------
123
124/**
125 * @brief Interface contract simulated as a struct holding only a function pointer.
126 */
127typedef struct ISpeaker {
128 void (*speak)(struct ISpeaker*); /**< Function pointer representing the contract. */
130
131/**
132 * @brief speak() implementation for InterfaceDog.
133 * @param self Pointer to the ISpeaker base within an InterfaceDog instance.
134 */
136 (void)self;
137 printf("bark\n");
138}
139
140/**
141 * @brief speak() implementation for InterfaceCat.
142 * @param self Pointer to the ISpeaker base within an InterfaceCat instance.
143 */
145 (void)self;
146 printf("meow\n");
147}
148
149/** @brief ISpeaker implementation that barks. */
150typedef struct { ISpeaker base; } InterfaceDog;
151/** @brief ISpeaker implementation that meows. */
152typedef struct { ISpeaker base; } InterfaceCat;
153
154/**
155 * @brief Initializes an InterfaceDog instance.
156 * @param d Pointer to the InterfaceDog instance to initialize.
157 */
159
160/**
161 * @brief Initializes an InterfaceCat instance.
162 * @param c Pointer to the InterfaceCat instance to initialize.
163 */
165
166/**
167 * @brief Contractual Dispatch via manual function-pointer lookup.
168 * @param s Pointer to the ISpeaker contract whose speak function pointer is invoked.
169 */
171 s->speak(s);
172}
173
174// ---------------------------------------------------------------------------
175// Part 4: Monomorphism - a single concrete struct with a directly-named
176// function, called without going through any function pointer at all.
177// There is only one implementation, so there is nothing to sever/redirect.
178// ---------------------------------------------------------------------------
179
180/** @brief The sole concrete "speaker" type; no vtable is needed. */
181typedef struct { int dummy; } PureBreedDog;
182
183/**
184 * @brief Direct, non-polymorphic speak implementation for PureBreedDog.
185 * @param self Pointer to the PureBreedDog instance.
186 */
188 (void)self;
189 printf("Woof\n");
190}
191
192/**
193 * @brief Scenario A: Monomorphic target - direct call, no vtable indirection.
194 * @param explicitDog Pointer to the concrete PureBreedDog instance.
195 */
196void directSpeak(PureBreedDog* explicitDog) {
197 PureBreedDog_speak(explicitDog);
198}
199
200/**
201 * @brief Entry point exercising all four polymorphism scenarios.
202 * @return 0 on successful completion.
203 */
204int main()
205{
206 // Part 1
207 Dog myDog; Dog_init(&myDog);
208 Cat myCat; Cat_init(&myCat);
209 makeSpeak(&myDog.base);
210 makeSpeak(&myCat.base);
211
212 // Part 2
214 makeSleep(&dog.base);
215
216 // Part 3
217 InterfaceDog iDog; InterfaceDog_init(&iDog);
218 InterfaceCat iCat; InterfaceCat_init(&iCat);
221
222 // Part 4
223 PureBreedDog pureDog;
224 directSpeak(&pureDog);
225
226 return 0;
227}
228
229// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
230// Debug program: F5 or Debug > Start Debugging menu
231
232// Tips for Getting Started:
233// 1. Use the Solution Explorer window to add/manage files
234// 2. Use the Team Explorer window to connect to source control
235// 3. Use the Output window to see build output and other messages
236// 4. Use the Error List window to view errors
237// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
238// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file
void PureBreedDog_speak(PureBreedDog *self)
Direct, non-polymorphic speak implementation for PureBreedDog.
void makeSpeak(Animal *a)
Dynamic Dispatch via manual function-pointer vtable.
void interfaceCatSpeak(ISpeaker *self)
speak() implementation for InterfaceCat.
void InterfaceCat_init(InterfaceCat *c)
Initializes an InterfaceCat instance.
void directSpeak(PureBreedDog *explicitDog)
Scenario A: Monomorphic target - direct call, no vtable indirection.
void InterfaceDog_init(InterfaceDog *d)
Initializes an InterfaceDog instance.
void dogSpeak(Animal *self)
speak() implementation for Dog.
void DogWithDefault_init(DogWithDefault *d)
Initializes a DogWithDefault instance.
void dogWithDefaultSpeak(AbstractAnimal *self)
speak() implementation for DogWithDefault.
void Animal_sleep(AbstractAnimal *aa)
A concrete default function shared by all "subclasses".
void Dog_init(Dog *d)
Initializes a Dog instance, wiring its vtable pointer to dogSpeak.
void makeSleep(AbstractAnimal *aa)
Dynamic Dispatch using abstract parent pointer.
void catSpeak(Animal *self)
speak() implementation for Cat.
void makeSpeakInterface(ISpeaker *s)
Contractual Dispatch via manual function-pointer lookup.
void Cat_init(Cat *c)
Initializes a Cat instance, wiring its vtable pointer to catSpeak.
int main()
Entry point exercising all four polymorphism scenarios.
void interfaceDogSpeak(ISpeaker *self)
speak() implementation for InterfaceDog.
Abstract base "class" combining shared state and an abstract speak function pointer.
void(* speak)(struct AbstractAnimal *)
Base "class" simulated as a struct holding a speak function pointer.
void(* speak)(struct Animal *)
"Subclass" of Animal that meows.
Animal base
"Subclass" of Animal that barks.
Animal base
Concrete AbstractAnimal "subclass" that implements speak().
AbstractAnimal base
Interface contract simulated as a struct holding only a function pointer.
void(* speak)(struct ISpeaker *)
ISpeaker implementation that meows.
ISpeaker implementation that barks.
The sole concrete "speaker" type; no vtable is needed.