分享
 
 
 

转贴:C++语言常见问题解:#1 ~ #15

王朝c/c++·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

这是我从台湾的http://www.cis.nctu.edu.tw/chinese/doc/research/c++/C++FAQ-Chinese/发现的《C++ Frequently Asked Questions》的繁体翻译,作者是:叶秉哲,也是《C++ Programming Language》3/e繁体版的译者,该文章是非常的好,出于学习用途而将它转贴,本人未取得作者的授权,原文章的版权仍然归属原作者.

C++语言常见问题解

=======================================================

■□ 第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 <iostream.h>

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++ 标准化方案在进行吗?

有的;ANSI(美国的)和 ISO(国际的)组织正密切合作。ANSI-C++ 委员会称为

"X3J16" ,而 ISO C++ 标准团体称为 "WG21"。ANSI/ISO C++ 的标准过程中包含了

这些人:

AT&T, IBM, DEC, HP, Sun, MS, Borland, Zortech, Apple, OSF 等等等等。每次开

会约有 70 人,他们来自美、英、日、德、瑞典、丹麦、法国……(他们都有「区域

性」的委员会,派遣正式代表并主导「区域性」的会议)。

========================================

Q7:该到哪里索取最新的 ANSI-C++ 标准草案?

ISO Committee Draft for C++ 以及 ANSI C++ Draft(将要供 public review 的文

件)可如此取得:

http://www.cygnus.com/~mrs/wp-draft

你也可以拿到 Postscript 和 Adobe Acrobat 的版本:

ftp://research.att.com/dist/stdc++/WP

也能拿到 HTML 和 ASCII 的版本:

ftp://ftp.cygnus.com/pub/g++

也能拿到书面版本:

X3 Secretariat

1250 Eye Street NW

Suite 200

Washington, DC 20005

202-626-5738

你也可以用 email:

lbarra@itic.nw.dc.us (Lynn Barra)

注明要索取最新的 "Draft Proposed American National Standard for Information

Systems -- Programming Language C++",文件编号 CD14882。它通常是用2日期的

FedEx(美国境内)来递送的,所以很快就能收到。

========================================

Q8:C++ 对 ANSI-C 回溯兼容吗?

几乎是。

C++ 尽可能地和 C 兼容,但不能更兼容了。事实上,主要的不同在于 C++ 要求函数

原型:"f()" 宣告的是无参数的函数(在 C 里,"f()" 和 "f(...)" 是一样的)。

还有些细微的差别,像在 C++ 里 sizeof('x') 等同于 sizeof(char),但在 C 里面

却是等同于 sizeof(int)。 而且,C++ 直接就把结构的卷标(tag)当成是型别的名

字,但 C 就需要加个 "struct" 字("typedef struct Fred Fred" 这种技巧仍然能

用,但在 C++ 中是累赘的)。

========================================

Q9:多久才能学会 C++?

像 Paradigm Shift 公司,成功地教授过标准的工业界「短期课程」,将大学一学期

的课压缩到一周 40 小时。然而真正的精通得由实际经验而来:没有东西能取代时间

。需动手做的指定专题是必要的,因为它们能将你的观念「凝固成形」。

大约要 6-12 个月才能流利使用 C++/OOP,如果身边有高手的话,费时会短些;反之

若没有个“好的”通用型 C++对象链接库,则会耗时更久。想成为顾问级的高手,则

约需 3 年。

有些人却根本办不到。除非你是可造之材,且有强烈的个人驱动力,否则你也做不到

。「孺子可教」最起码的要求是:你必须能「觉今是而昨非」。「驱动力」最起码的

要求是:你愿意多投入时间精力(改变思考的方式〔典范转移 paradigm shift〕要

远比学些新的东西来得困难)。

=========================

■□ 第4节:C++ 的基础

=========================

Q10:什么是类别(class)?

对象导向系统的基石。

类别是用来定义资料型态(data type)的,就像 C 的 struct 一样。

以信息科学术语来说,一个型态包含了一组状态(state),以及在状态之间转移的

动作行为(operation)。因此 "int" 是个「型态」,因为它有一组状态,还有诸如

「加两个整数」、「整数相乘」等等的运作行为。同样的,「类别」提供一组(通常

是公共的)运算,及一组(通常是非公共的)数据域位,以代表该型态的案例所拥有

的抽象值。以 C 的角度来看,类别就是其成员(members)皆预设为 "private" 的

struct。

把 "int" 想成是个类别,它拥有 "operator++" 等等的运作行为(method)。

========================================

Q11:什么是对象(object)?

一块赋有某种语意的储存空间。

在宣告 "int i;" 之后,我们称「i 是个 int 型态的对象」。在 C++/OOP 里,「物

件」通常意指「类别的案例(an instance of a class)」,因此类别定义了数个物

件(案例)的行为。

========================================

Q12:什么是参考(reference)?

一个对象的“别名”(alias,另一个名称)。

参考通常用于传址呼叫(pass-by-reference):

void swap(int& i, int& j)

{

int tmp = i;

i = j;

j = tmp;

}

main()

{

int x, y;

//...

swap(x,y);

}

在这里 "i" 和 "j" 分别是是 main 函数中 "x" 与 "y" 的别名,换句话说,"i" 就

是 "x"--不是个指向 "x" 的指针,也不是 "x" 该值的复制品,而它的的确确就是

"x" 本身。你对 "i" 做的任何动作,都会反映到 "x" 上;反之亦然。

从最底层来看,参考最常用指针来实作,它的效果有点像 C 里头的「传指针呼叫」

(pass-by-pointer),但 "&" 取址运操作数由呼叫者换到被呼叫者之处了,你也要删

去所有的 "*" 运操作数。

========================================

Q13:如果设定某值给参考会怎么样?

会更动到被参考者(referrent,该「参考」所参考到的对象)。

记住:「参考」就是「被参考者」,因此动了参考就会改动到被参考者(「参考」是

「被参考者」的左值 "Lvalue"〔出现在设定陈述的左边〕)。

更进一步,我们也允许参考被传回。这样子函数呼叫就可放在设定陈述的左边,这对

运操作数多载的场合很有用。

========================================

Q14:怎样才能将参考改设成别的对象?

没有办法。

和指针不同,一旦参考被系结到某个对象,它就不能再被改设到其它对象去。「参考

」本身不是一个对象(它自己没有地址;「取参考的地址」只会得到被参考者的地址

;切记:「参考」就是「被参考者」)。

将「参考」与「被参考者」分离开来是不可能的。

========================================

Q15:何时该用参考,何时又该用指针?

可以时,用参考;必要时,就用指针。

当你不需要“重设”它时(见前一个问题),参考会比指针好。这通常意味着:在物

件类别的公共接口中参考最有用。参考大多用于对象的表层,而指针则多用于里层。

但有一个例外:当函数参数或传回值需要一个「临界」(sentinel)的参考值时,最

好是用指针来做,以 NULL 指针做为一个特别值(「参考」应该是个实质对象的「别

名」,而不是个解参用的〔dereferenced〕NULL 指针)。

注意:老资格的 C 程序员不喜欢参考,因为在父程序的地方,「参考」的语意并不

是那么明显。然而有了些 C++经验后,会发现这正是一种「信息隐藏」的作法,是利

而非弊。好比说,程序员应该以切近该问题的方式来写程序,而非以机器的语言来解

题。

========================================

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有