| 热门文章 |
 |
|
| 编辑推荐 |
 |
|
|
|
|
|
作者:中译者:叶秉哲
来源:永远的UNIX 点击: 更新:2006-12-19
|
|
erized type)? Q121:「泛型」(genericity)是什麽? 第20节:程式库 ---------------- Q122:怎样拿到 "STL"? Q123:怎样 ftp 到 "Numerical Recipes" 附的程式? Q124:为什麽我的执行档会这麽大? 第21节:特定系统的细节 ------------------------ Q125:GNU C++ (g++) 把小程式造出大大的执行档,为什麽? Q126:有 YACC 的 C++ 文法吗? Q127:什麽是 C++ 1.2? 2.0? 2.1? 3.0? Q128:如果签名编码标准化了,我能否将不同厂商编译器产生的程式码连结起来? 第22节:其他的技术和环境的事项 -------------------------------- ⊙22A:其他的技术事项 Q129:为什麽有 static 资料成员的物件类别产生了 linker 错误? Q130:"struct" 和 "class" 关键字差别在哪? Q131:为什麽不能以函数的传回值来多载(overload)它? Q132:什麽是「持续性」?什麽是「持续性物件」? Q133:为什麽浮点数 (floating point) 这麽不精确?为什麽这段程式不会印出 0.43? ⊙22B:其他环境下的琐事 Q134:有任何 TeX 或 LaTeX 的巨集,能处理 "C++" 的留白效果(spacing)吗? Q135:在哪儿可拿到 C++2LaTeX 这个 C++原始码的 LaTeX 美编工具(pretty printer)? Q136:该到哪里取得 "tgrind" 这个 C++/C/etc 的原始码美编工具? Q137:有给 GNU emacs 编辑器用的 C++-mode 吗?有的话,该怎麽拿? Q138:我要到哪儿得到和作业系统相关的 FAQs( 譬如:BC++、DOS、Windows 等等)? Q139:为什麽我的 DOS C++ 程式说 "Sorry: floating point code not linked" “抱歉,浮点运算程式码未连结进来”? Q140:为什麽当我没执行 BC45 IDE 的话,BC++ 做出来的 Windows 应用程式就不能用? ========================= ● 1C:术语及常用的缩写 ========================= 这儿是一些此文件所采用的缩写: 字汇 意义 ==== =========== fn function ,函数(单数型) fns functions,函数(复数型) param parameter,参数 ptr pointer,指标,C/C++ 的语法元素,宣告法: int * p; ref reference,参考,C++ 的语法元素,宣告法: int & r; OO object-oriented,物件导向 OOP object-oriented programming,物件导向程式设计 OOPL object-oriented programming language,物件导向语言 method 运作行为,"member function 成员函数" 的另一种说法 【译注】"method" 是源自 Smalltalk 的术语,很常用於 OO 界。 ======================================================= ■□ 第2节:我该如何参与讨论?(发信之前请务必一读) ======================================================= Q1:我该在哪个讨论区中发问? Comp.lang.c++ 是讨论 C++语言本身最好的地方(譬如:C++ 程式设计、语法、风格 )。其他讨论区是用来讨论特定的系统(譬如:MS Windows 或是 UNIX),或是其他 和 C++语言不直接相关的主题(譬如:怎样使用你的编译器)。底下列出一些非常热 门的讨论区,并从它们的 FAQs 中摘录些片断,应该能让您明了它们最常讨论哪些课 题。 comp.os.ms-windows.programmer.tools 此区是用来讨论有关 Windows 软体发展系统工具的选择及使用。 comp.os.ms-windows.programmer.misc 此乃论及其馀 Windows 软体发展之事项。 [有个 FAQ 列表,列出所有 comp.os.ms-windows.programmer.* 讨论区] FAQ 5.7.1. 在 DLL 中存取 C++ 的物件类别 FAQ 6.1.1. 以 MDI 子视窗做出对话框 [用 OWL] FAQ 6.2.1. 把禁能的选项致能起来 [用 MFC] FAQ 8.1.5. 使用 windows.h 的 STRICT 符号定义 FAQ 10. 程式设计参考资料 comp.os.msdos.programmer 许多信件都是关於程式语言产品的(主要是 Borland 和 Microsoft)。 FAQ 301. 怎样才能读取字元而不 [等待] Enter 键? FAQ 412. 怎样读取、建立、更改及删除磁片标名? FAQ 504. 怎样设定 COM 埠,以用它来传输资料? FAQ 602. C 程式怎样才能送控制码给印表机? FAQ 606. 怎样才能得知 Microsoft 滑鼠的位置及按钮状态? FAQ 707. 怎样写常驻程式(TSR)工具? FAQ B0. 怎样连系 [Borland, Microsoft] 等公司? [注意:这份 FAQ 不在 rtfm.mit.edu 里;而在 Simtel (譬如 oak.oakland.edu) in /pub/msdos/info/faqp*.zip 以及 Garbo (garbo.uwasa.fi) in /pc/doc-net/faqp*.zip] comp.os.msdos.programmer.turbovision [Borland 的文字模式应用程式骨架] comp.unix.programmer FAQ 4.5) 怎样使用 popen() 开启行程以读写之? FAQ 4.6) 怎样在 C 程式里 sleep() 一秒以内? comp.unix.solaris (包含 SunOS 4.x 和 Solaris) FAQ 4) Signal 入门 FAQ 5) 等待子行程 Exit gnu.g++.help FAQ: 到哪里找 C++ 的 demangler(反签名编码器)? FAQ: 哪里有 Solaris 2.x 版的 gcc/g++ 位元档? FAQ: 有 g++ 2.x 的文件吗? gnu.g++.bug [g++ 的臭□列表 -- 请见 g++ 的文件] comp.lang.c FAQ 1.10: 我搞糊涂了。NULL 保证一定是 0,但是 null 指标却不是? FAQ 2.3: 那麽,在 C 里头「指标和阵列等价」是什麽意思? FAQ 4.2: [为什麽 "printf("%d\n," i++ * i++);" 有问题?] FAQ 7.1: 怎样写一个接收不定数目引数的函数? [stdarg.h 或是 varargs.h] FAQ 10.4: 怎麽宣告一个指向某种函数的指标阵列,而该函数的传回值为: 指向另一个传回字元指标的函数? 并请参考看看 comp.graphics、comp.sources.wanted、comp.programming,以及 comp.object(它的 FAQ 是个很棒的 OOP 入门、术语观念概论文件)。请记住: comp.std.c++ 是专门讨论和研议中的 ANSI/ISO C++ 标准方案(下文会提)“直接 ”相关的事项。 同时到上述信区和 comp.lang.c++ 去问同一个问题,几乎是没必要的(你是知道的 ,特定系统信区的读者不用机器语言写程式)。只因你的问题「真的很要紧」,就到 处发问,是个很坏的习惯。如果你在「正确的」信区没得到回音,且认为你非得在这 儿发信不可,请至少考虑一下,将这儿的回信重导回原来那个适当的信区。 在任何信区发问之前,你应当先读读它的 FAQ。你想问的可能就在上面,这样就可省 下你发信的时间,以及全世界数以千计的人类读你的信的时间。回答已经是 FAQ问题 的人,可能会因为白白浪费时间而烦扰不已;他们也可能会给你错误或不完整的解答 ,因为他们也没看过 FAQ。 「常见问题解答」文件每天 24 小时都可由 anonymous ftp (rtfm.mit.edu 的 /pub/usenet/comp.what.ever) 或是 e-mail server (寄一则内容为 "help" 的信到 mail-server@rtfm.mit.edu) 来取得。欲知详情,请见 "Introduction to the *.answers newsgroups" 这份文件,它在 news.answers 或 news.announce.newusers (这儿还有许多必须一读的文件)中找到。 ======================================== Q2:我该怎麽提出「我的程式有毛病」的问题呢? 底下是一些建议,让 comp.lang.c++ 的读者能帮你解决程式设计的问题。 1. 请读读上一个问题,以确定你的问题是针对 C++语言本身,而和你的程式设计系 统(譬如:绘图、印表机、设备……)或是编译环境(譬如:「整合环境挂了」 、「怎样消除xxxx警告讯息」、「怎样连结程式库」)完全无关。如果你想知道 为什麽你 OWL程式中的虚拟函数 CmOk() 没被呼叫到,你的问题可能比较适合放 在 Windows程式设计的信区。如果你能写个独立的小程式,而它会让编译器产生 和你那个 OWL程式同样的错误讯息或行为的话,就可以放到 comp.lang.c++ 了, 其他系统的 C++程式员可能帮得上忙。 2. 「信件标题」栏位要有意义。像是「C++ 程式」这样的标题太空泛了,「new 一 个多维阵列的问题」就很好。不要用一堆惊叹号,穷嚷嚷著「救命啊」,或是开 玩笑的用「SEX SEX SEX」这种标题。如果你认为该问题和你的编译器有关,最好 在标题栏中道出编译器和版本编号。 3. 列出完整的、可编译得过去的程式码。要从人类的语言叙述里,去除错或是重建 回一个程式,是极为困难的事。「完整的程式码」指的是:任何被用到的型别、 函数都要宣告出来,被用到的标头档都要 #include 进来……等等。请将程式码 裁减到只留必要的部份,我们并不需要那些执行起来(甚至连结时)“有用的” 东西,我们只须能重现出你的错误讯息(可能在不同的编译器中)就行了。「可 编译得过去」指的是:不要含有一堆未注解掉的 ... 这种删节号,或是各行行首 的行号: 14: #include 15: class Foo { ... }; // 像这样就是很讨人厌的东西! 将你的程式组织成线性结构,不要让我们再切割、制造些标头档案。请仔细输入 你的程式码--我们通常不容易判断:某个地方只是你的打字错误,抑或它真的 就是你的问题所在。尽量改用编辑器的「剪贴」或「插入档案」功能。 4. 列出你用的编译器、编译器版本,以及你使用的系统。我知道我刚刚说过:特定 系统的问题要去特定的信区发问,但和编译器有关的资讯,常常对侦查问题有帮 助(「喔,我记得 Acme 1.2 在这方面有很多毛病」),这也顺便提醒了那些编 译器的用户:小心那些毛病。 5. 把编译器、连结器的选项写出来,以及你用来建程式所用的程式库。 6. 把错误讯息和何处发生错误的资料写出来。像是「虚拟函数不能用了」并没告诉 我们这是个编译时段、连结时段还是执行期的问题。如果这问题是执行期发生的 ,请把它的行为,和任何相关的系统设定资讯列出来。 7. 在签名档中列出真的能用的 e-mail 地址。如果你信件的 "From:" 一栏有错的话 ,请通知你的系统管理者。在它修复前,於你的信件标头中加入 "Reply-To:" 一 栏,填上你正确的 e-mail 地址。 8. 请读读这份 FAQ 的其他部份--可能你的问题,或是很相关的问题就在这儿。 谢谢您,并希望以上的建议能协助您找到问题的解答。 =================================== ■□ 第3节:周遭的、管理上的事项 =================================== Q3:什麽是 OOP?什麽是 C++? 物件导向(OO)程式技术,是我们所知发展大型而复杂的软体系统最好的方法。 C++ 是个物件导向的程式语言。C++ 可当成一个物件导向程式语言(OOPL),亦可只 当成一个“更好的 C 语言”来使用。不过,若你只把它当成“更好的 C”,你就无 法获得物件导向程式设计的好处。 提一则 OO 的广告词:软体工业刻正无法应付大型而复杂的软体系统需求。但这正是 肇因於我们的「成果」:我们过去的成功促使大家要求得更多,不幸的是,这份市场 的渴求却是「结构化」分析(analysis)、设计(design)和程式设计所无法满足的 。因此,我们才得发展一个更好的典□(paradigm)。 ======================================== Q4:C++ 的优点是什麽? 「C++ 的成长」:C++ 是到目前为止最受欢迎的语言。每 7.5到 9个月 C++的使用者 都会加倍。「懂 C++」是个很好的求职资格(但你必须把它当成 OOPL,而不只是一 个更好的 C 来用才行)。 「封装性 encapsulation」:藉由隐藏内部的资料结构,让我们可以改变系统的某部 份,而不必更动其他部份。我们为软体元件(称之为 class,类别)提供一个安全的 介面,用户只碰得到这个介面而已;而相对起来比较容易变动的介面「实作」部份, 就被封装起来(就像被包在胶囊里),以避免用户过於依赖他一时的实作决定。在比 较简单的 C 里头,可由模组内的静态(static)资料来办到,以避免其他模组存取 到它。 「多重案例 multiple instances」:典型的 C 语言「封装」方法(刚才有提),做 不到多重的资料案例(我们很难替模组的 "static" 资料做出多重案例)。如果在 C 中要做到的话,我们得使用 "struct" 结构(但是它没有「封装性」)。在 C++里, 我们可用 "class"(物件类别)来做到多重案例与封装性:"public"公共部份包含了 它的介面(通常这里会有个特别的函数:成员函数),"private" 私有部份包含了它 的实作细节(通常这儿就是内部资料结构的所在)。 「行内函数呼叫」:在 C 中,可以在 struct 里放个 "void*"(该存取函数 [access functions] 会用到指标转型)来达到「封装的 structs」。这样会丧失型别安全性 ,而且会造成过多的函数呼叫,即使你只存取结构内的小小栏位(假如你允许直接存 取结构内栏位的话,它内部的资料结构就很难再变更了,因为你的程式有太多地方“ 依赖”它以前的样子)。函数呼叫的额外负担不大,但是会累积起来。C++ 的类别允 许函数作 "inline" 行内扩展,就有以下好处:□封装的安全性,□多重案例的方便 性,□直接存取的速度。而且,编译器也会检查行内函数的参数,这就比 C 的 #define 巨集更好了。 「多载运算子」:C++ 能对物件类别的运算子加以多载(overload),以合乎我们的 直觉(譬如,"myString + yourString" 可做字串串接,"myDate++"可用来递增日期 ,"z1 * z2" 可将两复数 z1 及 z2 相乘,"a[i]" 可用来存取 "a" 这个连结串列的 第 i 个元素……等等)。你甚至可以做出个“聪明的指标”(smart pointer),以指 向磁碟或其他地方去("x = *p" 可 dereference [解参用] 指标,也就可以在磁碟 中找到 p 所“指到”的地方,并传回其值)。这可让使用者以切近该问题的方式来 写程式,而非以机器的语言来解题。 【译注】STL (Standard Template Library) 就大量利用到「聪明的指标」功能。 「继承性 inheritance」:我们还只是在表层而已,事实上,我们还没进入「物件导 向」的部份呢!假设你有个 Stack 堆叠型态,有 push、pop 运算。若你还想要个 InvertableStack 型态,它“很像”Stack,只是它还有个 "invert" 运算。以 C 的 方式,你不是得□修改现存的 Stack模组(如果它在其他地方也用到的话,就麻烦了 ),就是得□把 Stack拷贝到另一个档案,再加以修改之(这会导致过多重复的程式 码、容易破坏到 InvertableStack 里某些源自 Stack 的小地方,尤有甚者,得维护 双倍的程式码)。C++提供了更乾净的解决法:继承。你可以说:「InvertableStack 继承了 Stack的一切,且 InvertableStack又添加了 invert 运算。」这样子就好了 !Stack本身仍然是封闭的(未被更动到),而 InvertableStack也没重复 push/pop 等的程式码。 「多型」与「动态系结」:OOP 真正的力量不仅是继承性,还有把 InvertableStack 当成是一个 Stack来传递的能力。这是安全的,因为(至少在 C++里)此乃「是一个 ……」的关系("is-a" relation),透过公共继承达到的(亦即:InvertableStack “是一个”Stack,且它还能自我 invert 反转)。多型(polymorphism)与动态系 结(dynamic binding)最容易从实例来理解了,所以我提个典型的例子:绘图软体 得处理圆形、方形、矩形、多边形及直线,这些都是「形状 shape」。大部份绘图软 体的内部函数都需要个“形状”的参数(相对於某些像是“方形”这种特定的形状) ,譬如:当我们用滑鼠选取某个图形,它就可能被拖曳放到萤幕某处。多型和动态系 结让程式能正确运作,即使编译器只知道该参数是个「形状」,而不知它到底是什麽 形状。我们再假设刚才提到的 "pick_and_drag(Shape*)" 函数於星期二编译好了, 到了星期三,你打算再加个六边形。听起来很奇怪,但 pick_and_drag() 仍然能够 处理这个六边形,即使当 pick_and_drag() 编译时六边形还不存在!(若你明了 C++ 是怎麽做的,它就再也不惊异了--但它仍然是很方便的!) ======================================== Q5:谁在用 C++? 很多很多的公司及政府部门。相当的多。 统计上来看:当你正在读这份 FAQ文字时,就有 5 个人正成为 C++的程式员。 ======================================== Q6:有任何 C++ 标准化方案在进上一页 [1] [2] [3] [4] [5] 下一页
|
|
|