Tag Archives: C++

需求分析VS惯用法

  让出Web开发和企业级开发领域后,C++集中于系统级开发,也就是一般应用软件的“硬核”部分。所以一个有趣的现象是,尽管C++的市场份额在下降,C++程序员的平均工资却在提高。

  但C++的复杂性一直让人头疼。最近关于C,C++,D语言的大争论,国内外都引起强烈反响。和以往“编程语言口水仗”不同,不少经验丰富的程序员和架构师发表了自己的意见。

  刘未鹏刚发布的这篇《学习C++:实践者的方法》值得推荐。学习C++容易钻到语言细节的牛角尖里出不来,相信很多人都有共鸣,而且身边的新人还在不断重复这种弯路。其实,对系统功能需求本身的理解和分析,比你用了几种惯用法和设计模式,重要得多。BLOG后半部分还给出了学习要点的列表,比较中肯。文中提到的Bjarne Stroustrup的回信Andrei Alexandrescu的专访云风的BLOG,都值得看一看。

  BTW1:下班时fy大侠评价:“系统跑得很流畅”。这一阶段的优化工作干得很苦,结果也令人欣慰:内存占用降到了老版本的1/5,从 而避免了进程空间2G上溢崩溃的问题,速度也有所提高。改进效果在越大的数据上越明显。human库同时指定5、6种可变修饰,pFind不再那么吃力 了。

  BTW2:近几个月的重构,“水面以下”的进展是以exception throw替代掉原有C风格的return false和GetLastError()。十几万代码,三十几个模块,逐步利用各种机会顺手重构,到今天算基本改完了。目前的异常和日志机制让我满意。 如果要列出用C++而不用C的最主要原因,我大概会选STL和异常处理。

  BTW3:闲暇时玩玩D语言,编程的感觉很好。变化的正是C++那些让人别扭的历史包袱。

Andrei Alexandrescu专访

  很多朋友都问参加SD2China(软件开发2.0大会)的感觉,还在“反刍”中,也想等等看别人的BLOG有什么整理。回过来审视自己手头的pFind 2.0工作,有了不少新的视点和思路。

  参加SD2China原因之一是冲着Andrei Alexandrescu去的,他的课程都听了,得到亲笔签名的C++ Coding Standards:101 Rules, Guidelines, and Best Practices。这里有段专访,里面提到C++0x标准提案里,他最喜欢的三个features是:variadic templates、auto和concept,说到俺心里去了。

最近C++0x信息收集

  列出最近看过的关于C++0x的一些链接,以发表时间排序:

  标准委员会总是磨磨蹭蹭的,0x里什么auto&decltype,Initializer,variadic templates,concepts和sequence point这些提案经过N长时间反复炒,都快失去新鲜感了。估计就算立刻出现在VC和gcc里,很多人也能拿起来就用。想了半天,没什么可写的,也许现在剩下的就是等着投票了。

C++应用程序和C++库

  引用孟岩的好文:

  “…… 现在我们知道,用来写C++程序库所需要的技术,与用来写C++应用程序所需要的技术存在很大的差别。这已经比较糟糕了。更糟糕的是,一般的C++开发者 根本分不清这中间的差别,他们在开发中往往既不是一个称职的程序库开发者,也不是一个单纯的应用开发者。他们一边想着完成手头的工作,一边琢磨如何能够写 出高质量的基础库和框架,为万世开太平。如果说C语言是一把轻快的小匕首,遇谁都是进身猛刺,血溅一尺,那么这种C ++的使用方式无异于左手打铁铸兵,右手挥剑刺秦,这种精神分裂的状态直接将很多项目变成了既超期超支又质量低劣的垃圾。“

   “认识到这样的事实之后,C++程序员应当以更理性的态度来看待自己的工作。大部分情况下,你所需要做的是寻找一些可以互相合作的、稳定可靠的开源程序 库,然后在其基础之上,面向目标,使用尽可能简朴的技术,专心专意地进行应用开发,把那些复杂精妙的语言技巧和“可复用”之类的想法扔到Java国去。唯 其如此,你才可能更高效地开发出好的应用软件,而且会逐渐积累和重构出真正可复用的软件。”

C++和集群系统

  现代C++的发展方向让人困惑:泛型技术的确很酷,却妨碍了模块的动态链接。没有Java Bean这样的标准组件模型可能算是C++语言最让人头疼的地方,程序员被各种编译器和操作系统的细节淹没。

  大型系统里,C++到底负责哪些部分更合适?时髦的体系结构是这样的:用C++实现library层,用Java甚至更华丽的动态语言实现业务层和界面层。看起来很美,比如Eclipse和SWT

  串联质谱鉴定系统搜索引擎pFind以外的模块如何组织?一直拿不定主意。

  上周去合作单位,实际操作同类的国外工业级产品,集群系统的体系结构给我留下了深刻印象:由C++实现各种独立的后台服务,无论命令行、Java GUI界面、分布式网络协议或Web界面方式,都能操作这些服务进程。的确是简明漂亮的方式。

  好的解决方案往往都很简单。比如集群节点间的通讯服务,其实只需相互交换简单的消息,再利用NETBIOSNFS共享具体数据就行了。

《Modern C++ Design》

  最近搜索浏览了一些关于template的blog,感觉自己可以开始看《Modern C++ Design》了。所以昨天抽空到中关村图书大厦买了中文版,候捷、於春景译,华中科技大学出版社,中文名是《C++设计新思维》

  浏览了第1章(Policy-Based Class)和第6章(Singletons),目前卡在第3章(Typelists)的迷魂阵里,计划接下来读第9章(Absract Factory)。

  对我这种只会用STL容器,看到大段尖括号就发晕的template菜鸟来说,这本书的学习曲线有些陡峭。但泛型编程和设计模式结合起来太酷了,每看懂几页,就会回忆起以前的某个笨拙设计,开始胡思乱想,踅摸如何重构。

  记笔记,下面是几条以前不知道的ABC:

  1. 虚函数不可以是templates
  2. 如果class template有个成员函数从未被调用,它就不会被编译器实现出来

后记:3月3日读完第一遍

用template模拟虚函数多态性

  以前写过关于对象的多态技术的讨论,提到传统的C++虚函数的做法,像对话框这样的接口,会产生一个巨大的虚函数表,调用时,实际都要执行两步:先通过虚函数表找到函数指针,然后再运行函数。

  那么C++有什么其他解决方法呢?可以借助模板技术。

  首先,Framework实现一个template作为接口:

template<class T>
class FrameworkBase1
{
public:
//调用接口
void HelloWorld(void)
{
static_cast<T *>(this)->SayHello();
};
//实际实现,这里提供一个默认版本,也可以不提供,类似纯虚基类
void SayHello(void)
{
cout<<“Hello World! This is FrameworkBase1n”;
};
protected:
//下面都是扮演Framework调用HelloWorld接口
void call1(void)
{
HelloWorld();
}
void call2(void)
{
HelloWorld();
}
};

  当用户打算实现这个接口,提供给Framework回调的时候,就这样:

class Derived1 : public FrameworkBase1<Derived1>
{
public:
//重新实现
void SayHello(void)
{
cout<<“Hello World! This is Derived1n”;
};
};

  当然,也可以采用Base1类的默认动作:

class Derived2 : public FrameworkBase1<Derived2>
{
//啥也不做,直接采用FrameworkBase1默认的实现
};

  Alan Kay评价:“……所有喜欢和擅长C++的人都必须是严肃认真的铁人,有足够能力在事前规划一切,如果不适应这种风格,大量细节会让你疯狂……”

对象的多态技术

  C++的虚函数机制,是通过一个虚函数表存放函数指针实现的,一旦子类重载了虚函数,就替换掉表里的指针。COM的原理与此很类似,其中Interface可以看作纯虚类。C++是静态语言,函数表没有自描述性,调用代码完全是编译器由指针偏移量编译得到的硬编码。也就是说,虚函数表是定长的,即使是子类没有实现的函数,也需要父类的函数指针来占位。

  而Ruby等新一代动态语言,因为包含元数据,可以根据方法的名称进行查找。子类实现了几个虚函数,它的查找表就有多长,找不到再扔给父类继续查找。

  思路上,两者都是插入一个中间层,拦截外界对方法的调用,按照具体的类信息指定实际执行的代码。两者也有差别:动态语言因为涉及到字符串比较,查找效率相对差,而C++运行效率更高;但如果一个C++的父类提供成千上万的虚方法接口,即使子类只实现其中一小部分,也必须带着一个巨大的函数表,这显然造成了空间浪费。

  典型的,GUI架构如果采用虚函数机制,即使再小的对话框,例如‘确认取消’,甚至是只需要实现OnClick()的一个按钮类,由于是从Window类继承下来的,都必须带着一个存放几百甚至上千函数指针的函数表。

  为了对付这种情况,MFC没有使用虚函数,而定义了一大堆宏进行事件消息分发,虽然语法风格很丑陋,但保证了效率;而.net框架,发展出delegate机制,呵呵,兜了一圈,我们又回到纯C的回调函数风格了。

  参考资料很多:元数据、反射和delegate机制的资料都源于网上;C++和COM技术参考这两本:《Inside The C++ Object Model》和《COM原理与应用》。