程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言面向對象編程(二):繼承詳解

C語言面向對象編程(二):繼承詳解

編輯:關於C

在 C 語言面向對象編程(一)裡說到繼承,這裡再詳細說一下。

C++ 中的繼承,從派生類與基類的關系來看(出於對比 C 與 C++,只說公有繼承):

派生類內部可以直接使用基類的 public 、protected 成員(包括變量和函數)使用派生類的對象,可以像訪問派生類自己的成員一樣訪問基類的成員 對於被派生類覆蓋的基類的非虛函數,在派生類中可以通過基類名和域作用符(::)來訪問當使用基類指針調用虛函數時,會調用指針指向的實際對象實現的函數,如果該對象未重載該虛函數,則沿繼承層次,逐級回溯,直到找到一個實現 上面的幾個特點,我們在 C 語言中能否全部實現呢?我覺得可以實現類似的特性,但在使用方法上會有些區別。後面我們一個一個來說,在此之前呢,先說繼承的基本實現。

先看 C 語言中通過“包含”模擬實現繼承的簡單代碼框架:

struct base{
    int a;
};

struct derived{
    struct base parent;
    int b;
};

struct derived_2{
    struct derived parent;
    int b;
};

上面的示例只有數據成員,函數成員其實是個指針,可以看作數據成員。 C 中的 struct 沒有訪問控制,默認都是公有訪問(與 java 不同)。

下面是帶成員函數的結構體:

struct base {
    int a;
    void (*func1)(struct base *_this);
};

struct derived {
    struct base parent;
    int b;
    void (*func2)(struct derived* _this;
};

為了像 C++ 中一樣通過類實例來訪問成員函數,必須將結構體內的函數指針的第一個參數定義為自身的指針,在調用時傳入函數指針所屬的結構體實例。這是因為 C 語言中不存在像 C++ 中那樣的 this 指針,如果我們不顯式地通過參數提供,那麼在函數內部就無法訪問結構體實例的其它成員。

下面是在 c 文件中實現的函數:

static void base_func1(struct base *_this)
{
    printf("this is base::func1\n");
}
static void derived_func2(struct derived *_this)
{
    printf("this is derived::func2\n");
}

C++ 的 new 操作符會調用構造函數,對類實例進行初始化。 C 語言中只有 malloc 函數族來分配內存塊,我們沒有機會來自動初始化結構體的成員,只能自己增加一個函數。如下面這樣(略去頭文件中的聲明語句):

struct base * new_base()
{
    struct base * b = malloc(sizeof(struct base));
    b->a = 0;
    b->func1 = base_func1;
    return b;
}

好的,構造函數有了。通過 new_base() 調用返回的結構體指針,已經可以像類實例一樣使用了:

struct base * b1 = new_base();
b1->func1(b1);

到這裡我們已經知道如何在 C 語言中實現一個基本的“類”了。接下來一一來看前面提到的幾點。

第一點,派生類內部可以直接使用基類的 public 、protected 成員(包括變量和函數)。具體到上面的例子,我們可以在 derived_func2 中訪問基類 base 的成員 a 和 func1 ,沒有任何問題,只不過是顯式通過 derived 的第一個成員 parent 來訪問:

static void derived_func2(struct derived *_this)
{
    printf("this is derived::func2, base::a = %d\n", _this->parent.a);
    _this->parent.func1(&_this->parent);
}


第二點,使用派生類的對象,可以像訪問派生類自己的成員一樣訪問基類的成員。這個有點變化,還是只能通過派生類實例的第一個成員 parent 來訪問基類的成員(通過指針強制轉換的話可以直接訪問)。代碼如下:

struct derived d;
printf("base::a = %d\n",d.parent.a);

struct derived *p = new_derived();
((struct base *)p)->func1(p);

有點晚了,剩下的改天再寫。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved