看板 CSSE 關於我們 聯絡資訊
※ 引述《tinlans ( )》之銘言: : 在有 OOP 的 polymorphism + dynamic binding 是怎樣用 C 模擬的呢? : 常見的答案是用一個 struct, : 內含一個 union 以及 int 變數 (當然也可以是 enum 或更小的整數型別), : union 存放 data 實體, : 而 int 變數用來指出它是什麼 type, : 於是乎 C programmer 會搞出一組 functions 來操作之, : 且必存在下列形式的 code: : switch(xxx.type) { : case TYPE_A: : ... : break; : case TYPE_B: : ... : break; : case TYPE_C: : ... : break; : ... : } 現代的 C programmer 大概會這麼做: typedef int myfun(int n); struct myclass; typedef struct myclass myclass; struct myclass { // data part ... myclass* p; // parent class (super class) int c; // data structure id of subclass (class id) void* d; // pointer to extended data of subclass int s; // data size of d // code part myfun* work; // member function ... }; int myclass_work(myclass* c, int n) { return (c->work)(n); } int def_myclass_work(int n); int class2_work(int n); myclass def_myclass_data = { ...., def_myclass_work }; myclass* def_myclass = &def_myclass_data; void sub_class(myclass* a, myclass* b, myfun* work) { memcpy(a, b, sizeof(myclass)); a->p = b; a->work = work; } void new_object(myclass* a, myclass* b, int c, void* d, int s) { memcpy(a, b, sizeof(myclass)); a->p = b; a->c = c; a->d = d; a->s = s; } void main() { myclass class2, object1; sub_class (&class2, def_myclass, class2_work); new_object(&object1, &class2, 0, NULL, 0); // create object1 of class2 myclass_work(&object1, 10); // call (*object1.work)(10) } 你可能會說,這不就是 OO 嗎? 沒錯,確實是 OO, 但誰說 C 就不能寫 OO 了? 既然是要實作 OO 機制,就不能亂拿別的東西魚目混珠。 像上例的 def_myclass 是靜態的 class, 但 class2 就是動態產生的 class, 這就是 C++ 沒有內建的 OO 特性了。 這程式碼很粗糙也不完整,所以比 C++ 難看許多,實際使用應該是要加上大量的 巨集,讓程式碼變得比較漂亮一些。 C 的自由度大,程式設計的紀律是極為重要的,這裡沒有做錯誤檢查,實際上是 每一個參數都要檢查的,也應該儘量預先建立一些系統機制,而不是在需要時才 臨時製作。 自由不是散漫,就是因為太多寫 C 的人都太散漫了,才會有 C++ 這種把檢查和 機制都預先做好,不讓你有太多自由的程式語言出現。不然 C 是真的很好用。 : 今天如果我需求變更, : 我要加入一個新的 type, : 那好玩的問題就來了, : C programmer 能幹出來的事情就只有剪貼, : 你說貼 code 很少會有人漏貼這也沒錯, : 但是問題這途中還會做一些修修改改, : 那你又要跑去每個 function 內做修改, : 漏掉一個就會變成最後很難抓到的 bug, : 但是 OOPL 就完全不必幹這種事情, : 因為有 polymorphism 跟 dynamic binding 的支援。 承上述做法,好的 C programmer 也不用幹這種事。 在一般情況下 C 程式不會去搞得跟 C++ 一樣,如果大部分都要使用 C++ 提供的 機制,不如就使用 C++. : C programmer 要做到完全安全的程度, : 只有每改一個 function 就完整的 test 一次, 常常會改 function 表示該 function 還是未完成品,正常來說是不需要的。 : 不過我想大家都寫過程式, : 其可行性大概是幾 % 應該不用我來講。 : 我也知道透過 preprocessor 的一些技巧可以祭出不少大絕招來維護一致性, : 但是: : 1. 其實遇上這種情形的話效果十分有限, : 因為每個 function 還是有獨立的 statements, : 而可讀性也會因此降低。 : 2. 幾乎所有的 debugger 都不可能 step into 到 macro 內, : debugging 的時候會搞死人。 要大量產生程式碼,不管是用什麼 preprocessor, 最好都產生實際的程式碼 再做編譯。 另外建議自行實作 debug mode 的 error message. 可減少對 debugger 的 依賴。基本上我已經不使用 debugger 了。 要用 C 來寫程式就不能只有 C, 有很多機制和程式設計方法要自行累積建立。 : 像是 Open-Closed Principle 在 C language 也不可能實現, /* 我是笨蛋,不知道想到哪裡去了,完全搞錯. open-closed 這部分刪掉 */ 基本上我回應這些,是想要說,寫程式的是人,所以 programmer 的觀念、 能力、努力和自我要求,才是程式好壞的關鍵。 程式語言終究是軟體開發工具的一部分,它不能代替人決定程式是好還是壞。 這就跟許多人用 IDE 開發軟體,但還是有少數人只用文書處理軟體寫程式, 往往這些人還比較厲害,這種狀況放在 C++ 和 C 上面也是一樣。 軟體品質的問題說也說不完,只是對於軟體品質沒有概念的人,用好的工具 也不會自動就能寫好程式。 當然我也贊同軟體品質經由電腦輔助會很有用,然而那未必就是程式語言, 正如同 C++ 在 garbage collection 上的立場一樣,有些機制是可以自行 建立,並且在多數時候可以用別的方式來完成,不見得一定要靠那些機制。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.222.173.26 ※ 編輯: semop 來自: 61.222.173.26 (01/05 01:46)
HZYSoft:gtk+ 就是 C 寫 OO 的最佳範例,甚至有很多 C++ 沒的功能 01/05 21:29