用C實現OOP面向對象編程(1)

如摘要所說,C語言不支持OOP(面向對象的編程)。並這不意味着咱們就不能對C進行面向對象的開發,只是過程要複雜許多。原來以C++的許多工做,在C語言中需咱們手動去完成。git

博主將與你們一塊兒研究一下以下用C語言實現面象對象的編程。shell

面向對象的三大特性:封裝、繼承、多態編程


咱們要達到的目的以下:函數

Animal是動物,有兩個方法:Eat()吃,Breed()繁衍。oop

Bird與Mammal都是Animal,Mammal是哺乳動物。測試

Penguin是企鵝,企鵝是Bird,企鵝不會飛。優化

Swallow是燕子,是Bird,會飛。ui

Bat是蝙蝠,是Mammal,會飛spa

Tiger是老虎,是Mammal,不會飛。.net

Plane是飛機,會飛。它不是動物。

從上面的類繼承關係來看,因爲Swallow, Bat, Plane會飛,因此它們都繼承了IFly接口。


首先咱們用C++的類來實現上面的關係:

class Animal {
public:
    virtual void Eat() = 0;
    virtual void Breed() = 0;
};

class Bird : public Animal {
public:
    virtual void Breed() {
        cout << "蛋生" << endl;
    }
};

class Mammal : public Animal {
public:
    virtual void Breed() {
        cout << "胎生" << endl;
    }
};

class IFly {
public:
    virtual void Fly() = 0;
};

class Penguin : public Bird {
public:
    virtual void Eat() {
        cout << "企鵝吃魚" << endl;
    }
};

class Swallow : public Bird , public IFly {
public:
    virtual void Eat() {
        cout << "燕子吃蟲子" << endl;
    }
    virtual void Fly() {
        cout << "燕子飛呀飛" << endl;
    }
};

class Bat : public Mammal, public IFly {
public:
    virtual void Eat() {
        cout << "蝙蝠吃飛蟲" << endl;
    }
    virtual void Fly() {
        cout << "蝙蝠飛呀飛" << endl;
    }
};

class Tiger : public Mammal {
    virtual void Eat() {
        cout << "老虎吃肉" << endl;
    }
};

class Plane : public IFly {
public:
    virtual void Fly() {
        cout << "飛機飛過天空" << endl;
    }
};

用下面的main.cpp來測試它們的繼承效果:

int main()
{
    Penguin *penguin = new Penguin;
    Swallow *swallow = new Swallow;
    Bat *bat = new Bat;
    Tiger *tiger = new Tiger;
    Plane *plane = new Plane;

    Animal* animals[4] = {penguin, swallow, bat, tiger};
    IFly* flies[3] = {swallow, bat, plane};

    for (int i = 0; i < 4; ++i) {
        animals[i]->Eat();
        animals[i]->Breed();
    }

    cout << "-------------" << endl;
    for (int i = 0; i < 3; ++i)
        flies[i]->Fly();

    delete penguin;
    delete swallow;
    delete bat;
    delete tiger;
    delete plane;

    return 0;
}

執行的效果是:

企鵝吃魚
蛋生
燕子吃蟲子
蛋生
蝙蝠吃飛蟲
胎生
老虎吃肉
胎生
-------------
燕子飛呀飛
蝙蝠飛呀飛
飛機飛過天空

上面演示的就是C++的多態功能。


多態這個特性給咱們軟件靈活性帶來了很大的便利。因爲某此限制,如硬件資源不夠充裕、開發環境不支持C++等原理,咱們不能使用C++。

那麼咱們下面要討論的是用C來從新實現上面的多態功能。

main.c大體是這樣子的:

int main()
{
    Object* penguin = Penguin_New();
    Object* swallow = Swallow_New();
    Object* bat = Bat_New();
    Object* tiger = Tiger_New();
    Object* plane = Plane_New();

    Object* animal[4] = {penguin, swallow, bat, tiger};

    IFly* flies[3] = {NULL};
    flies[0] = Swallow_AsIFly(swallow);
    flies[1] = Bat_AsIFly(bat);
    flies[2] = Plane_AsIFly(plane);

    for (int i = 0; i < 4; ++i) {
        Animal_Eat(animal[i]);
        Animal_Breed(animal[i]);
    }

    for (int i = 0; i < 4; ++i) {
        IFly_Fly(flies[i]);
    }

    Penguin_Delete(penguin);
    Swallow_Delete(swallow);
    Bat_Delete(bat);
    Tiger_Delete(tiger);
    Plane_Delete(plane);

    return 0;
}

上面編譯時須要加 "-std=c99" 才能經過編譯。


博主已實現了上面的Demo,代碼已提交到:http://git.oschina.net/hevake_lcj/C_OOP_DEMO

該Demo實現了OOP的類繼承、多態的特性。繼承只支持單繼承,尚未實現接口功能。

每一個對象由三部分組成:info, data, func

  • info,類信息,存儲該對象的:類型ID、虛函數表地址

  • data,對象的數據

  • func,虛函數指針

以下爲 info 的定義:

typedef struct {
    uint32_t tag;   //! 高16位爲TAG,低16位爲class_id
    void* vfun;     //! 虛函數結構體地址
} class_info_t;

例如 Animal 類的定義,見 animal_def.h :

typedef struct {
    int health; 
} Animal_Data;

typedef struct {
    void (*Eat)();
    void (*Breed)();
} Animal_Func;

typedef struct {
    class_info_t info;
    Animal_Data data;
    Animal_Func func;
} Animal;

結構圖:

<明天再寫>

即將討論話題:

- 如何表述類的繼承關係?

- 爲何要將data與func分開?


博主本身測試了一下,結果是:

$ ./c_oop_demo
start
企鵝吃魚
蛋生
燕子吃蟲子
蛋生
蝙蝠吃飛蟲
胎生
老虎要吃肉
胎生
end

從上看來,已達到了預期的多態效果。


C++與C的比較

居說C++編譯出來的可執行文件遠多於C。因而博主對比了一下c_oop_demo與C++編譯的同功能的可執行文件cpp_demo。博主驚訝地發現 c_oop_demo 的文件大小既還比 cpp_demo大一點。何況上面的 c_oop_demo 尚未實現接口功能呢,要是實現了,那不更大?這不禁令博主對用C實現OOP,覺得能夠節省空間的想法大爲失望。

看來,在實現一樣的oop功能下,C++編譯出的輸出文件比本身手把手寫的c_oop_demo要小,說明C++在這方便作了很多的優化。相比之下,C++用50多行的代碼實現的功能,用C(博主親自統計的)竟然要寫近1000行代碼。代碼的可維護性遠不及C++。說C++生成的文件龐大,真是冤枉了C++。用C完成同等功還不如C++幹得漂亮。

相關文章
相關標籤/搜索