学C++越学越有味是怎么回事

C++ 用户说:『我基本上兼容 C,而且我有很多高级特性!你想要底层控制力,那么你可 以在 C++ 里面写 C 啊。』

在说这个之前,我先用 Common Lisp 举个例子。

Emacs 论坛里,大家或多或少都听说过 Common Lisp。Common Lisp 的对象系统叫做 CLOS, CLOS 支持一种叫 MOP (Metaobject Protocol)的技术。用户可以通过 MOP 修改 class和 object 很多行为,比如怎么分配 slot,怎么继承 superclass,怎么决定 class precedence list等。那有了 CLOS+MOP,我能表达所有抽象,岂不美哉?

非也!CLOS 太过强大,要表达一些受限的抽象反而容易造成混乱。比如我用 CLOS 去表达 GTK 的 GObject 对象系统。

GObject 只支持单继承,而 CLOS 默认支持多继承。那我的抽象是否需要支持多继承?这时 候库的开发者就陷入了两难境地。支持多继承,如果用户要同时继承多个 GObject 对象怎 么办,我应该听谁指挥?甚至不同的父类还会有不同的 metaclass,用户还必须指定应该用 哪个 metaclass。不支持多继承,用户就得留着心眼看某些 class 是否支持多继承,与 CLOS 的『直觉』相违悖。

CLOS 的 MOP 当然可以『解决』这个问题,只要用 MOP 修改类的行为,解决掉多继承的冲 突,那么又可以快乐地多继承了… 但是,我并不认为这是一个好的抽象,因为为了使用抽象 (从 GObject class 里继承),用户被迫陷入琐碎的实现细节中(研究父类的 metaclass)。

做加法容易,做减法难。C 可能表达能力比较欠缺,实现某个抽象。写起来各种函数指针乱 飞,比较丑。但 C++ 为了实现某个抽象用上了 template,class 继承这些高级特性。却容 易在暗中留下坑,等着无知的程序员掉进坑里

另一个我想吐槽的事情,就是‘超市买菜’模型。很多人在设计语言的时候,都会有如下的思 路:‘X是好的,Y是好的,Z是好的,我也刚好都需要,所以我这个语言要有X, Y, Z。’,比 如上面那个人,就认为‘FP是好的,OOP是好的,我都需要,于是我去设计语法去了’

这样做的问题是完全没考虑到各种feature之间的互相影响-而这才是设计语言最麻烦的地 方。

-- 《超市买菜》

10 个赞