Khi sử dụng struct
để mô tả các bản ghi dữ liệu mô phỏng về các thực thể, có những trường hợp nhất định khi giữa các thực thể có tính chất kế thừa các đặc tính, hiển nhiên chúng ta cũng muốn phản ánh đặc trưng kế thừa inheritance
trong code thay vì tổ hợp composition
. Tính năng kế thừa inheritance
không được C
hỗ trợ biểu thị về mặt cú pháp, tuy nhiên về mặt kĩ thuật thì mặc định là tính năng này đã được triển khai đối với các struct
khi làm việc thông qua các con trỏ struct pointer
.
Struct Pointer
Khi làm việc với các struct
thông qua con trỏ tham chiếu, chúng ta luôn có địa chỉ của struct
chính là địa chỉ của trường dữ liệu đầu tiên trong định nghĩa của kiểu struct
đó.
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
Điều này có nghĩa là nếu như chúng ta lưu địa chỉ của một struct_person
ở vị trí trường dữ liệu đầu tiên của một kiểu struct
khác thì kiểu struct
mới định nghĩa sẽ có thể được xem là một kiểu kế thừa từ class Person
. Bởi giả sử nếu chúng ta đang có một con trỏ Worker
kế thừa từ Person
theo cách này, một hàm được định nghĩa có tham số đầu vào là Person
cũng sẽ hoạt động tốt nếu chúng ta truyền vào địa chỉ của ô nhớ đầu tiên lưu trữ kiểu 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 | Class : Person Name : Semi Dev_ Age : 1001 |