天天看點

如何使用C語言的面向對象

我們都知道,C++才是面向對象的語言,但是C語言是否能使用面向對象的功能?

(1)繼承性

1 typedef struct _parent
2 {
3 int data_parent;
4 }Parent;
5 typedef struct _Child
6 {
7 struct _parent parent;
8 int data_child;
9 }Child;      

 在設計C語言繼承性的時候,我們需要做的就是把基礎資料放在繼承的結構的首位置即可。這樣,不管是資料的通路、資料的強轉、資料的通路都不會有什麼問題。

(2)封裝性

class的類成員預設情況下都是private,而struct的成員都是public(不能改變),是以如何讓C語言實作封裝的功能呢?答案就是函數指針;這在核心中得到了廣泛的應用;

1 struct _Data;
2 typedef  void (*process)(struct _Data* pData);
3 typedef struct _Data
4 {
5     int value;
6     process pProcess;
7 }Data;      

   封裝性的意義在于,函數和資料是綁在一起的,資料和資料是綁在一起的。這樣,我們就可以通過簡單的一個結構指針通路到所有的資料,周遊所有的函數。封裝性,這是類擁有的屬性,當然也是資料結構體擁有的屬性。

(3)多态性

在C++中,多态通常都是使用虛函數來實作的,但是C語言中并沒有虛函數,如何實作重載呢?

1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 //虛函數表結構
  5 struct base_vtbl
  6 {
  7     void(*dance)(void *);
  8     void(*jump)(void *);
  9 };
 10 
 11 //基類
 12 struct base
 13 {
 14     /*virtual table*/
 15     struct base_vtbl *vptr;
 16 };
 17 
 18 void base_dance(void *this)
 19 {
 20     printf("base dance\n");
 21 }
 22 
 23 void base_jump(void *this)
 24 {
 25     printf("base jump\n");
 26 }
 27 
 28 /* global vtable for base */
 29 struct base_vtbl base_table =
 30 {
 31         base_dance,
 32         base_jump
 33 };
 34 
 35 //基類的構造函數
 36 struct base * new_base()
 37 {
 38     struct base *temp = (struct base *)malloc(sizeof(struct base));
 39     temp->vptr = &base_table;
 40     return temp;
 41 }
 42 
 43 
 44 //派生類
 45 struct derived1
 46 {
 47     struct base super;
 48     /*derived members */
 49     int high;
 50 };
 51 
 52 void derived1_dance(void * this)
 53 {
 54     /*implementation of derived1's dance function */
 55     printf("derived1 dance\n");
 56 }
 57 
 58 void derived1_jump(void * this)
 59 {
 60     /*implementation of derived1's jump function */
 61     struct derived1* temp = (struct derived1 *)this;
 62     printf("derived1 jump:%d\n", temp->high);
 63 }
 64 
 65 /*global vtable for derived1 */
 66 struct base_vtbl derived1_table =
 67 {
 68     (void(*)(void *))&derived1_dance,
 69     (void(*)(void *))&derived1_jump
 70 };
 71 
 72 //派生類的構造函數
 73 struct derived1 * new_derived1(int h)
 74 {
 75     struct derived1 * temp= (struct derived1 *)malloc(sizeof(struct derived1));
 76     temp->super.vptr = &derived1_table;
 77     temp->high = h;
 78     return temp;
 79 }
 80 
 81 
 82 
 83 int main(void)
 84 {
 85 
 86     struct base * bas = new_base();
 87     //這裡調用的是基類的成員函數
 88     bas->vptr->dance((void *)bas);
 89     bas->vptr->jump((void *)bas);
 90 
 91 
 92     struct derived1 * child = new_derived1(100);
 93     //基類指針指向派生類
 94     bas  = (struct base *)child;
 95 
 96     //這裡調用的其實是派生類的成員函數
 97     bas->vptr->dance((void *)bas);
 98     bas->vptr->jump((void *)bas);
 99     return 0;
100 }      

繼續閱讀