繼承就是當建立乙個類時,不需要重新編寫新的資料成員和成員函式,只需指定新建的類繼承了乙個已有的類的成員即可。這個已有的類稱為基類,新建的類稱為派生類。
舉個例子:人是動物,人具有動物的行為和屬性,但人也有動物所不具備的行為和屬性。
動物行為
屬性會動體力人
行為屬性
會動體力
會學習智力
本實現使用了組合的方式,即把基類作為派生類的成員變數之一。
但是一定要將基類放在派生類首部,這要基類和派生類的記憶體首部分布才一致。
/* 基類 */
typedef struct _animal_t animal_t; /* 動物類 */
struct _animal_t
;
/* 派生類 */
typedef struct _human_t human_t; /* 人類 */
在派生類中的建構函式需要呼叫基類的建構函式用於初始化,然後再將建構函式建立的基類物件拷貝到派生類中。
但由於是淺拷貝,即只拷貝了位址,沒有拷貝位址的內容。所以要在派生類中加入基類指標成員變數,用於在析構函式釋放記憶體。
typedef struct _human_t human_t;/* 人類 */
struct _human_t
;human_t* human_born(void); /* 建構函式 */
void human_die(human_t* this); /* 析構函式 */
human_t* human_born(void)
void human_die(human_t* this)
typedef struct _animal_t animal_t; /* 動物類 */
struct _animal_t
;void act(void* this); /* 動 */
typedef struct _human_t human_t;/* 人類 */
struct _human_t
;void learn(void* this);
void act(void* this)
else
}
void learn(void* this)
else
}
在上個例子中,人和動物都有會動的屬性,但人的動作和動物的動作從表現上會有所不同。而多型就可以實現在同乙個函式中,根據物件型別的不同,函式實現方式也不同。
c語言多型的實現,需要用到函式指標。函式名實際上是該函式**儲存空間的首位址,這個位址可以通過函式指標來存放。通過改變函式指標儲存的位址就可以實現多型。
typedef struct _animal_t animal_t;
typedef void (*animal_act_t)(animal_t*); /* 函式指標型別 */
typedef struct _animal_vtable_t /* 虛函式表 */
animal_vtable_t;
struct _animal_t
;animal_t* animal_born(void); /* 建構函式 */
void act(void* this); /* 函式介面 */
void animal_die(animal_t* this); /* 析構函式 */
static void animal_act(animal_t* this);
/* 動物類的虛函式表 */
static animal_vtable_t __g_animal_vtable =
;animal_t* animal_born(void)
void act(void* this)
/* 實現函式 */
static void animal_act(animal_t* this)
else }
void animal_die(animal_t* this)
該**將結合上述繼承和多型的方法實現對基類函式進行重寫:
/* animal.h */
#ifndef _animal_h_
#define _animal_h_
#include #include #include typedef struct _animal_t animal_t;
typedef void (*animal_act_t)(animal_t*);
typedef struct _animal_vtable_t
animal_vtable_t;
struct _animal_t
;animal_t* animal_born(void);
void act(void* this);
void animal_die(animal_t* this);
#endif /* _animal_h_ */
/* animal.c */
#include "animal.h"
static void animal_act(animal_t* this);
static animal_vtable_t __g_animal_vtable =
;animal_t* animal_born(void)
void act(void* this)
printf("can't act\n");
}static void animal_act(animal_t* this)
else }
void animal_die(animal_t* this)
/* human.h */
#ifndef _human_h_
#define _human_h_
#include "animal.h"
typedef struct _human_t human_t;
typedef void (*human_learn_t)(human_t*);
typedef struct _human_vtable_t
human_vtable_t;
struct _human_t
;human_t* human_born(void);
void learn(void* this);
void human_die(human_t* this);
#endif /* _human_h_ */
/* human.c */
#include "human.h"
static void human_act(human_t* this);
static void human_learn(human_t* this);
static animal_vtable_t __g_animal_vtable;
static human_vtable_t __g_human_vtable =
;human_t* human_born(void)
void learn(void* this)
printf("can't learn\n");
}static void human_act(human_t* this)
else }
static void human_learn(human_t* this)
void human_die(human_t* this)
/* main.c */
#include "animal.h"
#include "human.h"
int main()
結果如下:
C語言實現繼承與多型
在前面部落格已經詳細講過c 中繼承與多型的概念,在這裡則只使用c語言的語法來實現繼承與多型。繼承 即派生類中擁有基類的成員變數和成員函式,所以c語言實現如下 include typedef void func void void funb typedef struct b b typedef str...
C語言實現繼承和多型
一 面向過程程式設計與物件導向程式設計的區別 眾所周知,c語言是一種典型的面向過程程式語言,而c 確實在它的基礎上改進的一款物件導向程式設計語言,那麼,面向過程與物件導向到底有什麼樣的區別呢?從設計方法角度看 面向過程程式設計方法採用函式 或過程 來描述對資料的操作,但又將函式與其操作的資料分離開來...
C語言實現封裝 繼承 多型
c語言中雖然沒有類,但有struct和指標。我們可以在乙個struct中存入資料和函式指標,以此來模擬類行為。typedef struct parent parent typedef struct child child include include 模擬乙個類a typedef struct a...