4.2 哪儿出问题
我们通常有特别的适应能力,即使是对本不应该适应的事情。CStash库的风格对于C程序员已经是常用的了,但是如果观察它一会儿,就会发现它是相当笨拙的。因为在使用它时,必须向这个库中的每一个函数传递这个结构的地址。而当读这些代码时,这种库机制会和函数调用的含义相混淆,当试图理解这些代码时也会引起混乱。
在C中,使用库的最大的障碍之一是名字冲突(name clashes)。对于函数,C使用单个名字空间,当连接器查找一个函数名时,它在一个主表中查找,而且,当编译器编译一个单元时,它只能对带有指定名字的单个函数进行处理工作。
假设决定要从不同的厂商购买两个库,并且每一个库都有一个必须被初始化和清除的结构。两个厂商都认为initialize()和cleanup()是好名字。如果在某个处理单元中同时包含了这两个库文件,C编译器怎么办呢?幸好,标准C出错,报告声明函数有两个不同的参数表中类型不匹配。即便不把它们包含在同一个处理单元中,连接器也会有问题。好的连接器会发现这里有名字冲突,但有些编译器仅仅通过查找目标文件表,按照在连接表中给出的次序,取第一个找到的函数名(实际上,这可以看做是一种功能,因为可以用自己的版本替换一个库函数)。
无论哪种情况,都不允许使用包含具有同名函数的两个C库。为了解决这个问题,C库厂商常常会在它们的所有函数名前加上一个独特字符串。所以,initialize()和cleanup()可能变为CStash_initialize()和CStash_cleanup()。这是合乎逻辑的,因为它“修饰了”这个struct的名字,而该函数以这样的函数名对这个struct操作。
现在到了迈向C++第一步的时候。我们知道,struct内部的标识符不会与全局标识符冲突。而当一些函数在特定struct上运算时,为什么不把这一优点扩展到函数名上呢?也就是,为什么不让函数成为struct的成员呢?