这是对 老谭的C语言教程一个问题 的讨论。
我浏览了 ChinaUinx 网站上网友的 留言,现在将个人认为有 价值 的回复转帖如下:
(如果侵犯回帖的权益,请通知我即刻删除,谢谢):
1#---------------->>>网友Shan_Ghost
在 .h 文件里实现函数有什么不妥之处,include .c就有同样的问题;或者说include .c能解决什么问题,在头文件里实现函数就也能解决什么问题。
而且,.h里声明函数虽然会导致某些特定问题,但有经验的C/C++程序员一看到就可以有心理准备,知道该如何对待;而include .c文件,出同样的问题就会隐蔽得多。
再次,对于一个C/C++程序员来说,凡没有声明在 .h 里的函数,都是模块的内部函数;那么只要保持本模块内部的同步,这个函数可以改名、改接口、改返回值——改它的内部行为就更不用说了。
【模块的内外部函数】
但是,一旦include了.c文件,那么这种保证将荡然无存。对新接触这些include了.c文件的工程代码的人来说,这个软件必然处处都是炸弹,任何地方都不敢碰不敢摸,否则它就会在完全八杆子打不着的地方爆炸——然后哭笑不得的发现,它把你的内部实现include进去了。
这是对最基本的编程规则的挑衅,也是对最基本的编程理念的颠覆。
2#----------------->>>Shan_Ghost
5#---------------->>>Shan_Ghost
6#--------------------->>>language(PDP-7)
![](http://bbs3.chinaunix.net/images/common/back.gif)
你做一个商业函数库供别人使用,如果里面包含可见非公开函数,你怎么能保证你的用户在连接你的库和其它另一具有同样特征的函数库的时候绝对不会发生冲突?
你这完全是无视了 static 关键字。如果你在认为可能发生命名冲突的内部函数声明前面加个 static,那就根本不会发生冲突,所有声明为 static 的全局符号都只在本模块中可见。
7#----------------------->>>Shan_Ghost
1、 对c/c++编译器来说,扩展名不对应任何功能
这就好像 “匈牙利命名法” 不会给编译器增加任何功能一样。
同样,绝不存在什么“因为用了匈牙利命名法,结果导致程序无法完成什么功能”的情况。
这点我反复强调过,反复车轱辘回来很没意思。
2、既然扩展名不提供任何功能,那么遵循扩展名的一般约定就不会产生/抑制任何技术问题。
唯一的差异,就是愿不愿意拿规范当回事。
愿意遵守规范,那么无论是在 .h里实现、在 .inc 里实现(STL的典型做法)还是在 .share .code 里实现,都可以在尽量不违反基本规范的前提下解决问题——除了扩展名有所改变,不会有其他任何痛苦;但整个项目一下子就q清爽多了,其他人就不需要疑惑究竟哪些.c文件敢碰,哪些.c摸都别摸了。
3、正如前面一位朋友所说的: 命名空间是做什么的? std:xx 和 std_xxx有本质区别吗?
如果真有合理的模块划分、并且还无法利用命名空间的话, 模块名_xxx 是否可以保证没有冲突?
4、事实上,如果真想解决问题,在.h+.c框架内完全可以做到。无非是对源码组织的要求更高了一点而已。
在 xx.h中include yy.h,相当于公开被引用的yy.h的接口;在xx.c中include yy.h,相当于隐藏 yy.h 提供的接口。
把某个内部模块先独立编译成静态库,然后再把这个内部静态库编译进供别人使用的模块(也编译成库),这样就可以避免内部模块的符号被暴露出去。
递归应用以上规则,有什么解决不了的?
5、wo level hen high, I dou can ba han yu pin sound xie de nobody neng look dong.(呵呵。。。)
8#----------------------->>>CMAX
村夫,你说了这么多我想我明白你的意思了,但我认为shan_ghost也明白你的意思了,并且他有提出了一个解决方案,只是这个解决方案在你看来和include .c相同罢了,可能shan_ghost说的过于正统化了,我就我的理解说下:
解决村夫你这种情况,确实使用正统的方式已经难以解决了,需要采用include .c的方式了,但约定俗成下.c文件是不应该被include的,那么这个时候为何不将这个需要被include的.c文件改名为.share或者.c_share文件,并且对这种后缀的文件做一个重点说明,这样可以有效的解决你那个问题,也给后边维护的人一个提醒,这个文件被share了,如果修改会有风险,而不是面对一通的.c文件,不晓得那个被share过,那个没有,连想修改的勇气都没有了.
规范是用来遵守的,虽然有时候规范里会发生解决不了的事,我们可以用规范以外的方式完成,但不要给这种方法也套上规范的外衣,让别的不知情的人一头雾水.
采用命名规范也是一种方式,不过面向全世界范围也确实有其风险,至于风险是多少,就得自己评估了.
总之使用什么方式是自己选择的事,但也要开始没参与过的人可以用约定俗成的规范理解你的做法.
9#---------------------->>>fluke
我没有深入研究过这方面,不过还是想问一下,extern能不能解决你这个问题?
a.c要用到b.c里面定义的函数(又不愿意在头文件暴露出来),那么在a.c里面用extern声明一下是在外部有实体可以链接,这个方案看起来貌似可以解决哦。
10#--------------------->>>ivhb
.......
【上面已是一场论战了,目前不能把握,先留着以待剖解】