推 HZYSoft:gtk+ 就是 C 寫 OO 的最佳範例,甚至有很多 C++ 沒的功能 01/05 21:29
※ 引述《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)