When using struct
to describe simulated data records about entities, there are certain cases when between entities there is inheritance of properties, obviously we also want to reflect the inherited characteristic. inheritance
in code instead of composition
combination. inheritance
is not syntactically supported by C
, but technically by default this feature has been implemented for struct
when working through struct pointer
.
Structure Pointer
When working with struct
through reference pointers, we always have the address of struct
which is the address of the first data field in the definition of that struct
type.
1 2 3 4 5 6 7 8 9 10 11 12 13 | typedef struct { char* class; char* name; int age; } person_struct; person_struct person (char* $name, int $age); typedef person_struct* Person; Person new_Person (char* $name, int $age); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string">"Person.h"</span></span> person_struct <span class="token function">person</span> <span class="token punctuation">(</span> <span class="token keyword">char</span> <span class="token operator">*</span> $name <span class="token punctuation">,</span> <span class="token keyword">int</span> $age <span class="token punctuation">)</span> <span class="token punctuation">{</span> person_struct $primitive <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span> class <span class="token operator">=</span> <span class="token string">"Person"</span> <span class="token punctuation">,</span> <span class="token punctuation">.</span> name <span class="token operator">=</span> $name <span class="token punctuation">,</span> <span class="token punctuation">.</span> age <span class="token operator">=</span> $age <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> $primitive <span class="token punctuation">;</span> <span class="token punctuation">}</span> Person <span class="token function">new_Person</span> <span class="token punctuation">(</span> <span class="token keyword">char</span> <span class="token operator">*</span> $name <span class="token punctuation">,</span> <span class="token keyword">int</span> $age <span class="token punctuation">)</span> <span class="token punctuation">{</span> person_struct $primitive <span class="token operator">=</span> <span class="token function">person</span> <span class="token punctuation">(</span> $name <span class="token punctuation">,</span> $age <span class="token punctuation">)</span> <span class="token punctuation">;</span> Person $reference <span class="token operator">=</span> <span class="token operator">&</span> <span class="token punctuation">(</span> $primitive <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> $reference <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><stdio.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string">"Person.h"</span></span> <span class="token keyword">void</span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> $argc <span class="token punctuation">,</span> <span class="token keyword">char</span> <span class="token operator">*</span> $argv <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> Person $me <span class="token operator">=</span> <span class="token function">new_Person</span> <span class="token punctuation">(</span> <span class="token string">"Semi Dev_"</span> <span class="token punctuation">,</span> <span class="token number">1001</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"Class: %s"</span> <span class="token punctuation">,</span> $me <span class="token operator">-></span> class <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"References: n"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">" struct: %p"</span> <span class="token punctuation">,</span> $me <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">" .class: %p"</span> <span class="token punctuation">,</span> <span class="token operator">&</span> <span class="token punctuation">(</span> $me <span class="token operator">-></span> class <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 5 | Class: Person References: struct: 0x7ffd01db6890 .class: 0x7ffd01db6890 |
Backward Casting
This means that if we store the address of a struct_person
as the first data field of another struct
type, the newly defined struct
type can be considered an inheritor of class Person
. Because if we have a Worker
pointer that inherits from Person
in this way, a function defined with an input parameter of Person
will also work fine if we pass in the address of the first cell to be stored. Store the type Worker
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include "Person.h" typedef struct { person_struct super; char* class; int stamina; } worker_struct; worker_struct worker (char* $name, int $age, int $stamina); typedef worker_struct* Worker; Worker new_Worker (char* $name, int $age, int $stamina); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string">"Worker.h"</span></span> worker_struct <span class="token function">worker</span> <span class="token punctuation">(</span> <span class="token keyword">char</span> <span class="token operator">*</span> $name <span class="token punctuation">,</span> <span class="token keyword">int</span> $age <span class="token punctuation">,</span> <span class="token keyword">int</span> $stamina <span class="token punctuation">)</span> <span class="token punctuation">{</span> person_struct $super <span class="token operator">=</span> <span class="token function">person</span> <span class="token punctuation">(</span> $name <span class="token punctuation">,</span> $age <span class="token punctuation">)</span> <span class="token punctuation">;</span> worker_struct $primitive <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span> super <span class="token operator">=</span> $super <span class="token punctuation">,</span> <span class="token punctuation">.</span> class <span class="token operator">=</span> <span class="token string">"Worker"</span> <span class="token punctuation">,</span> <span class="token punctuation">.</span> stamina <span class="token operator">=</span> $stamina <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> $primitive <span class="token punctuation">;</span> <span class="token punctuation">}</span> Worker <span class="token function">new_Worker</span> <span class="token punctuation">(</span> <span class="token keyword">char</span> <span class="token operator">*</span> $name <span class="token punctuation">,</span> <span class="token keyword">int</span> $age <span class="token punctuation">,</span> <span class="token keyword">int</span> $stamina <span class="token punctuation">)</span> <span class="token punctuation">{</span> worker_struct $primitive <span class="token operator">=</span> <span class="token function">worker</span> <span class="token punctuation">(</span> $name <span class="token punctuation">,</span> $age <span class="token punctuation">,</span> $stamina <span class="token punctuation">)</span> <span class="token punctuation">;</span> Worker $reference <span class="token operator">=</span> <span class="token operator">&</span> <span class="token punctuation">(</span> $primitive <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> $reference <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><stdio.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string">"Worker.h"</span></span> <span class="token keyword">void</span> <span class="token function">put_person</span> <span class="token punctuation">(</span> Person $person <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"Class : %s n"</span> <span class="token punctuation">,</span> $person <span class="token operator">-></span> class <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"Name : %s n"</span> <span class="token punctuation">,</span> $person <span class="token operator">-></span> name <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"Age : %i n"</span> <span class="token punctuation">,</span> $person <span class="token operator">-></span> age <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">void</span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> $argc <span class="token punctuation">,</span> <span class="token keyword">char</span> <span class="token operator">*</span> $argv <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> Worker $me <span class="token operator">=</span> <span class="token function">new_Worker</span> <span class="token punctuation">(</span> <span class="token string">"Semi Dev_"</span> <span class="token punctuation">,</span> <span class="token number">1001</span> <span class="token punctuation">,</span> <span class="token number">10000</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">put_person</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token keyword">void</span> <span class="token operator">*</span> <span class="token punctuation">)</span> $me <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 | Class : Person Name : Semi Dev_ Age : 1001 |