作者semop (semop)
看板CSSE
标题Re: [讨论] 念完资工之後...
时间Fri Jan 5 00:58:04 2007
※ 引述《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)
1F:推 HZYSoft:gtk+ 就是 C 写 OO 的最佳范例,甚至有很多 C++ 没的功能 01/05 21:29