分享
 
 
 

C++语言常见问题解答(1)

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

C++语言常见问题解答(1)

中译者:叶秉哲 (2001-04-27 13:05:08)

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

(USENETcomp.lang.c++的FAQ文件中译)

原作者:MarshallCline(cline@cheetah.ece.clarkson.edu)

(cline@parashift.com)

中译者:叶秉哲(william@tiger.cis.nctu.edu.tw)

原文件:USENETcomp.lang.c++FAQ,Jan31,1996.

版权声明:完全依照原作者MarshallCline於此文件中所示之版权事项

(请见下文之"COPYRIGHT"部份)。

如欲对本中译文件作授权事项之外的处理,请先洽本译者。

责任事项:完全比照原作者MarshallCline於此文件中所示之声明事项

(请见下文之"NOWARRANTY"部份)。

中译事项:笔者虽尽力使此中译文件合乎信、达的要求,但仍恐有未逮之处,

故有任何出入之处,请以原文为准。

任何笔者为中译、诠释所需而加注的地方,都以【译注】符号

标示出来。

本译文位置:以URL(UniformResourceLocator)格式说明。

FTP用户:

ftp://ftp.cis.nctu.edu.tw/Documents/News/C-faq/c-cppfaq.zip

WWW用户:

ftp://ftp.cis.nctu.edu.tw/Documents/News/C-faq/Index.html

各大BBS的programming精华区也可能收录,但以前述地点最新。

尔後,随原文件之新版而异动时,会在news:tw.bbs.comp.language发布。

<附>本文件中译的授权:

---------------QuoteBegin---------------

Fromcline@cheetah.ece.clarkson.eduMonOct1011:56:591994

Return-Path:

Received:fromcheetah.ece.clarkson.edubycis.nctu.edu.tw(4.1/SMI-4.1)

idAA18895;Mon,10Oct9411:56:46CST

Received:bycheetah.ece.clarkson.edu(4.1/SMI-4.1)

idAA06374;Sun,9Oct9423:59:49EDT

Date:Sun,9Oct9423:59:49EDT

From:cline@cheetah.ece.clarkson.edu(MarshallCline)

Message-Id:<9410100359.AA06374@cheetah.ece.clarkson.edu>

To:is80001@cis.nctu.edu.tw

In-Reply-To:WilliamYeh'smessageofSat,24Sep9410:31:48CST

<9409240231.AA20537@cissun51.cis.nctu.edu.tw>

Subject:"C++FAQ"bookfromAddison-Wesley

Reply-To:cline@sun.soe.clarkson.edu(MarshallCline)

Status:OR

>Date:Sat,24Sep9410:31:48CST

>From:is80001@cis.nctu.edu.tw(WilliamYeh)

>Newsgroups:comp.lang.c++

>X-Newsreader:TIN[version1.2PL2]

>

>Hi,

>

>We,studentsatDepartmentofComputer&InformationScience,enjoy

>yourelectronic-formedC++FAQverymuch.We'dliketotranslateit

>intoournativeChineseforthosehavingdifficultytoreadEnglish

>articles.

>

>Thetranslatedarticleismeanttobeusedasanelectronicdocument

>onInternet,andnotforcommercialuse.We,therefore,askforyour

>grantsforthistranslation.

>

>Regards.

>

>studentatcis.nctu.edu.tw

>--

>------------------------------------------------

>WilliamYeh|E-mailaddress:

>|is80001@cis.nctu.edu.tw

>Dept.ofComputer&Info.Science|u8023001@cc.nctu.edu.tw

>NationalChiao-TungUniversity,|william.bbs@bbs.cis.nctu.edu.tw

>Hsinchu,Taiwan,R.O.C.|

>------------------------------------------------

Thatsoundslikeawonderfulidea.

Permissiongranted.

M.

---------------QuoteEnd---------------

【中译对照表】

底下列出本文出现的专有名词、其他重要的词儿,与译者采用的中译,视上下

文情况,它们也可能会有两种以上的译名。可能的话,括号中也会附上一些其

他书籍文章中常见的译法。

abstraction抽象化.

access存取.

accessfunction存取函数.

alias别名.

argument引数.

arity元数.

assignment设定.

associativity结合律.

baseclass基底类别.

binding系结.

call呼叫.

class类别、物件类别.

composition成份、零件.

constructor建构子(建构元).

container容器.

containerclass容器类别.

datamember资料成员.

declaration宣告<名词>.

declare宣告<动词>.

default预设、内定.

define定义<动词>.

definition定义<名词>.

dereference解参用、解参考.

derive衍生.

destructor解构子(解构元).

dispatch分派、函数分派.

dynamic动态.

encapsulation封装、封装性.

exception例外、例外状况(异常).

exceptionhandling例外处理.

explicit明显的、外显的<形容词>.

expression运算式.

friend夥伴.

function函数.

genericity泛型.

headerfile标头档(引入档、含括档).

hide遮蔽.

hierarchy阶层.

identity个体识别.

implement实作<动词>.

implementation实作<名词>.

inherit继承<动词>.

inheritance继承<名词>.

inline行内(列内、内嵌).

inspector查询子.

instance案例、实体(执行个体).

instantiate案例化、实体化<动词>.

instantiation案例<名词>.

keyword关键字、保留字.

mangle签名编码<动词>.

mangling签名编码<名词>.

member成员.

memberfunction成员函数.

memberobject成员物件.

method运作方法、运算方法.

module模组.

multipleinheritance多重继承.

mutator更动子.

object物件(个体).

OO物件导向(个体导向).

OOP物件导向程式设计.

operator运算子.

overload多载(过荷、负载)<动词>.

overloading多载(过荷、负载)<名词>.

override覆盖、改写.

parameter参数.

persistence持续性(永续性、持固性)<名词>.

persistentobject持续性物件.

pointer指标.

polymorphism多型(同名异式).

precedence优先序.

prettyprinter美编工具.

private私有.

protected保护.

prototype原型、函数原型(雏型).

public公共、公有.

purevirtualfunction纯虚拟函数.

reference参考、参考值.

relation关系.

returnvalue传回值.

semantics语意.

signature签名、型态签名.

smartpointer聪明的指标.

specialization特异化、特殊化.

statement陈述、指令(指述).

static静态.

structure结构、记录.

subclass子类别、子代类别.

subtype子型别、子型态.

superclass父类别、亲代类别.

syntax语法、文法.

template样版(模版).

throw丢出.

type型态、型别.

virtual虚拟.

virtualfunction虚拟函数.

【中译版本异动纪录】

85.02.对整篇译文做比较多一点的修饰。

84.05.修饰些method相关的译名。

84.03.修饰些persistence、instance相关的译名。

84.01.一些译文修饰、增加此中译文件的ftp栖身处说明。

将覆盖(override)与遮蔽(hide)二词更明显地区分开来。

对「聪明的指标」(smartpointer)加一点诠释。

83.12.一些译文修饰、将"method"统一译为「运算方法」。

83.11.第一次发布,原载於交大资科系刊「资讯人园地」。

底下就是此USENETcomp.lang.C++FAQ文件的正文。

==Part1/4============================

【译注】原文件因篇幅过长,在发布时就已分成四份。

comp.lang.c++FrequentlyAskedQuestionslist(withanswers,fortunately).

Copyright(C)1991-96MarshallP.Cline,Ph.D.

Posting1of4.

1/96更新:

*关於恢复fron.soe.clarkson.edu的anonymousftp方式仍无下文。

*本月份没什麽变动。

9/95更新:

*加入FAQ41:以变数做为多维阵列的第一维度。

*加入FAQ123:关於"NumericalRecipes"的程式。

*加入第20节("程式库")。内容还很少,但总是个开端。

*修正FAQ30的错误(少了"i"变数)。

*加入FAQ124:使用动态连结以避免过於庞大的执行档。

*加入FAQ32:想在binary模式下"reopen"cin及cout的问题。

*加入ftpANSI/ISOCommitteeDraft的资讯(FAQ7)。

7/95更新:

*小地方(除了下面会提到的FTP地点的变动之外)。

6/95更新:

*更正订阅ANSI-C++Draft的电子邮递信箱。

*添加关於浮点运算的FAQ[PhilStaite所提的]。

*添加关於多维阵列的FAQ[DougShapter所提的]。

*添加关於中断服务常式(ISR),以及指向成员函数的指标之FAQ。

*重排关於「用'new'来配置某些类别的物件」FAQ的位置。

5/95更新:

*一些语句修饰。

4/95更新:

*添加BC++Windows方面常见的问题。

*更改NIHCL的ftp位址。

*添加解释:"ARM"代表"AnnotatedReferenceManual"。

3/95更新:

*添加关於"deletethis"的问题。

*添加两则关於iostreams与eof的问题。

*更正些Gnuemacs的"c-mode"和"cc-mode"的项目。

1/95更新:

*此文件的中译版出来了;底下再详述之。

12/94更新:

*添加关於STL的FAQ(放在#115)。

*添加关於签名编码的FAQ(放在#119)。

*更正「『成份』与『私有继承』之比较」这项FAQ里面的一些打字错误。

*更正一些拼字错误。

11/94更新:

*加入「FAQ书」和「FAQ文件」的区别资讯。

*其他字面上的修饰。

10/94更新:

*修正一些打字错误。

9/94更新:

*一点文字上的修饰。

8/94更新:

*加入"typeid"和"dynamic_cast"的新规定。

*加入"mutable"和"const_cast"的新规定。

*重写大部份的回答部份,使其更一致些。

*原文的引号改为"..."而不是`...'或``...''。

*有程式码例子的那一行以TAB起头;其他行则否。

【译注】本中译版以8个英文空白字元代替TAB。

*所有东西都编辑过了;到处都有小更动。

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

■□第1节:内容介绍

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

DOCUMENT:Frequently-Asked-Questionsforcomp.lang.c++

REVISION:Jan31,1996

文件不等於书本:这份C++FAQ文件和「FAQ书」是不一样的。“FAQ书”

("C++FAQs",Addison-Wesley,1995)是这篇文件的五倍大。

底下有更详细的介绍。

AUTHOR:MarshallP.Cline,Ph.D.

ParadigmShift,Inc.

OneParkSt./Norwood,NY13668

voice:315-353-6100

fax:315-353-6110

email:cline@parashift.com

COPYRIGHT:Copyright(C),1991-96MarshallP.Cline,Ph.D.

Permissiontocopyallorpartofthisworkisgranted,

providedthatthecopiesarenotmadeordistributed

forresale(exceptanominalcopyfeemaybecharged),

andprovidedthattheAUTHOR,COPYRIGHT,&NOWARRANTY

sectionsareretainedverbatimandaredisplayed

conspicuously.Ifanyoneneedsotherpermissionsthat

aren'tcoveredbytheabove,pleasecontacttheauthor.

NOWARRANTY:THISWORKISPROVIDEDONAN"ASIS"BASIS.THEAUTHOR

PROVIDESNOWARRANTYWHATSOEVER,EITHEREXPRESSOR

IMPLIED,REGARDINGTHEWORK,INCLUDINGWARRANTIESWITH

RESPECTTOITSMERCHANTABILITYORFITNESSFORANY

PARTICULARPURPOSE.

版权声明:Copyright(C),1991-96MarshallP.Cline,Ph.D.

复制本文件全部或部份的内容,若合乎下述诸项要求,则允许之

:不得为转售之目的而制作或传播任何复制品(但可索取名义上

的传播手续费),并且作者栏、版权声明及责任事项的部份,要

一字不漏地、醒目地显示出来。若您需要此处未提及的授权事项

,请洽本作者。

责任事项:这份文件是供您参考用的。对於本作品可能造成的营利性、或任

何特殊场合适用性之保障,作者概不负责,不论是否曾明白地指

出或暗示。

【译注】上述的「版权声明」与「责任事项」译文,仅供参考,一切请以

原文为准。译者对它们亦概不负责……;->

文件取得方法:旧的FTP地点不能用了。我正在寻找新的地点,

请密切注意下个月的这个地方。

请不要寄信来推荐新的地点(我的信箱会爆满的:)

【译注】台湾使用者,请到以下地点,或其AFSclient取得:

ftp://NCTUCCCA.edu.tw/USENET/FAQ/comp/lang/c++/FAQ*

其他资讯:comp.lang.cFAQ每个月都会出现在该讨论区中,

该文件的维护者是SteveSummit(scs@eskimo.com)。

中文翻译:用"Big5"内码(在台湾最广为使用的16位元中文内码)储存

的中文译文,可用anonymousftp到以下地点取得:

ftp://ftp.cis.nctu.edu.tw/Documents/News/C-faq/c-cppfaq.zip

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

●1A:「FAQ书」与「FAQ文件」

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

Addison-Wesley已出版了由Cline与Lomow合著的"C++FAQs"(1995,ISBN

0-201-58958-3)一书,许多人对该书和这篇文件的关系感到好奇,一些没看过该书

的人,也担心本文是否会和它相同。此处将回答这些问题。

「FAQ书」(於Oct.94上市)大体上和本文的观念一致,但该书约为本文的5倍

大,还包括了数千则交互参考资讯、参考资料、索引项目,及许多的程式例子。

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

●1B:目录

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

==========POSTING#1==========

第1节:内容介绍

----------------

⊙1A:「FAQ书」与「FAQ文件」

⊙1B:目录

⊙1C:术语及常用的缩写

第2节:我该如何参与讨论?(发信之前请务必一读)

------------------------------------------------

Q1:我该在哪个讨论区中发问?

Q2:我该怎麽提出「我的程式有毛病」的问题呢?

第3节:周遭的、管理上的事项

----------------------------

Q3:什麽是OOP?什麽是C++?

Q4:C++的优点是什麽?

Q5:谁在用C++?

Q6:有任何C++标准化方案在进行吗?

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

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

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

第4节:C++的基础

------------------

Q10:什麽是类别(class)?

Q11:什麽是物件(object)?

Q12:什麽是参考(reference)?

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

Q14:怎样才能将参考改设成别的物件?

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

Q16:行内函数是做什麽的?

第5节:建构子和解构子

----------------------

Q17:建构子(constructor)是做什麽的?

Q18:怎样才能让建构子呼叫另一个同处一室的建构子?

Q19:解构子(destructor)是做什麽的?

第6节:运算子多载

------------------

Q20:运算子多载(operatoroverloading)是做什麽的?

Q21:哪些运算子可以/不能被多载?

Q22:怎样做一个"**"「次方」运算子?

第7节:夥伴

------------

Q23:夥伴(friend)是什麽?

Q24:「夥伴」违反了封装性吗?

Q25:夥伴函数的优缺点?

Q26:「夥伴关系无继承及递移性」是什麽意思?

Q27:应该替类别宣告个成员函数,还是夥伴函数?

第8节:输入/输出:和

---------------------------------------------

Q28:该怎样替"classFred"提供输出功能?

Q29:为什麽我该用而不是以前的?

Q30:为什麽我处理输入时,会超过档案的结尾?

Q31:为什麽我的程式执行完第一次回圈後,会对输入的要求不加理睬?

Q32:在DOS及OS/2的binary模式下,要怎样来"reopen"cin及cout?

==========POSTING#2==========

第9节:自由记忆体管理

----------------------

Q33:"deletep"会删去"p"指标,还是它指到的资料,"*p"?

Q34:我能"free()"掉由"new"配置到的、"delete"掉由"malloc()"配置到的

记忆体吗?

Q35:为什麽该用"new"而不是老字号的malloc()?

Q36:为什麽C++不替"new"及"delete"搭配个"realloc()"?

Q37:我该怎样配置/释放阵列?

Q38:万一我忘了将"[]"用在"delete"由"newFred[n]"配置到的阵列,会发生

什麽事?

Q39:成员函数做"deletethis"的动作是合法的(并且是好的)吗?

Q40:我该怎麽用new来配置多维阵列?

Q41:C++能不能做到在执行时期才指定阵列的长度?

Q42:怎样确保某类别的物件都是用"new"建立的,而非区域或整体/静态变数?

第10节:除错与错误处理

------------------------

Q43:怎样处理建构子的错误?

Q44:如果建构子会丢出例外的话,该怎麽处理它的资源?

第11节:Const正确性

----------------------

Q45:什麽是"constcorrectness"?

Q46:我该早一点还是晚一点让东西有常数正确性?

Q47:什麽是「const成员函数」?

Q48:若我想在"const"成员函数内更新一个「看不见的」资料成员,该怎麽做?

Q49:"const_cast"会不会丧失最佳化的可能?

第12节:继承

--------------

Q50:「继承」对C++来说很重要吗?

Q51:何时该用继承?

Q52:怎样在C++中表现出继承?

Q53:把衍生类别的指标转型成指向它的基底,可以吗?

Q54:Derived*-->Base*是正常的;那为什麽Derived**-->Base**则否?

Q55:衍生类别的阵列「不是」基底的阵列,是否表示阵列不好?

⊙12A:继承--虚拟函数

Q56:什麽是「虚拟成员函数」?

Q57:C++怎样同时做到动态系结和静态型别?

Q58:衍生类别能否将基底类别的非虚拟函数覆盖(override)过去?

Q59:"Warning:Derived::f(int)hidesBase::f(float)"是什麽意思?

⊙12B:继承--一致性

Q60:我该遮蔽住由基底类别继承来的公共成员函数吗?

Q61:圆形"Circle"是一种椭圆"Ellipse"吗?

Q62:对「圆形是/不是一种椭圆」这两难问题,有没有其他说法?

⊙12C:继承--存取规则

Q63:为什麽衍生的类别无法存取基底的"private"东西?

Q64:"public:"、"private:"、"protected:"的差别是?

Q65:当我改变了内部的东西,怎样避免子类别被破坏?

⊙12D:继承--建构子与解构子

Q66:若基底类别的建构子呼叫一个虚拟函数,为什麽衍生类别覆盖掉的那个虚拟函

数却不会被呼叫到?

Q67:衍生类别的解构子应该外显地呼叫基底的解构子吗?

⊙12E:继承--Private与protected继承

Q68:该怎麽表达出「私有继承」(privateinheritance)?

Q69:「私有继承」和「成份」(composition)有多类似?

Q70:我比较该用哪一种:成份还是私有继承?

Q71:我应该用指标转型方法,把「私有」衍生类别转成它的基底吗?

Q72:保护继承(protectedinheritance)和私有继承有何关连?

Q73:"private"和"protected"的存取规则是什麽?

第13节:抽象化(abstraction)

-------------------------------

Q74:分离介面与实作是做什麽用的?

Q75:在C++里,我该怎样分离介面与实作(像Modula-2那样)?

Q76:ABC("abstractbaseclass")是什麽?

Q77:「纯虚拟」(purevirtual)成员函数是什麽?

Q78:怎样替整个类别阶层提供列印的功能?

Q79:何时该把解构子弄成virtual?

Q80:虚拟建构子(virtualconstructor)是什麽?

==========POSTING#3==========

第14节:程式风格指导

----------------------

Q81:有任何好的C++程式写作的标准吗?

Q82:程式撰写标准是必要的吗?有它就够了吗?

Q83:我们的组织该以以往C的经验来决定程式撰写标准吗?

Q84:我该在函数中间或是开头来宣告区域变数?

Q85:哪一种原始档命名惯例最好?"foo.C"?"foo.cc"?"foo.cpp"?

Q86:哪一种标头档命名惯例最好?"foo.H"?"foo.hh"?"foo.hpp"?

Q87:C++有没有像lint那样的指导原则?

第15节:Smalltalk程式者学习C++之钥

---------------------------------------

Q88:为什麽C++的FAQ有一节讨论Smalltalk?这是用来攻击Smalltalk的吗?

Q89:C++和Smalltalk的差别在哪?

Q90:什麽是「静态型别」?它和Smalltalk有多相似/不像?

Q91:「静态型别」与「动态型别」哪一种比较适合C++?

Q92:怎样分辨某个C++物件程式库是否属於动态型别的?

Q93:在C++里怎样用继承?它和Smalltalk有何不同?

Q94:Smalltalk/C++不同的继承,在现实里导致的结果是什麽?

Q95:学过「纯种」的OOPL之後才能学C++吗?

Q96:什麽是NIHCL?到哪里拿到它?

第16节:参考与数值语意

------------------------

Q97:什麽是数值以及参考语意?哪一种在C++里最好?

Q98:「虚拟资料」是什麽?怎麽样/为什麽该在C++里使用它?

Q99:虚拟资料和动态资料有何差别?

Q100:我该正常地用指标来配置资料成员,还是该用「成份」(composition)?

Q101:动态配置成员物件有三个效率因素,它们的相对代价是多少?

Q102:"inlinevirtual"的成员函数真的会被"inline"吗?

Q103:看起来我不应该用参考语意了,是吗?

Q104:参考语意效率不高,那麽我是否应该用传值呼叫?

==========POSTING#4==========

第17节:和C连结/和C的关系

--------------------------------

Q105:怎样从C++中呼叫C的函数"f(int,char,float)"?

Q106:怎样才能建一个C++函数"f(int,char,float)",又能被C呼叫?

Q107:为什麽linker有这种错误讯息:C/C++函数被C/C++函数呼叫到?

Q108:该怎麽把C++类别的物件传给/传自C的函数?

Q109:C的函数能不能存取C++类别的物件资料?

Q110:为什麽我总觉得C++让我「离机器更远了」,不像C那样?

第18节:指向成员函数的指标

----------------------------

Q111:「指向成员函数的指标」和「指到函数的指标」的型态有差别吗?

Q112:怎样把指向成员函数的指标传给signalhandler、Xeventcallback等等?

Q113:当我想以成员函数做为中断服务常式(ISR)时,为什麽编译器产生(型态不

符)的错误?

Q114:为什麽我取不出C++函数的位址?

Q115:怎样宣告指向成员函数的指标阵列?

第19节:容器类别与template

-----------------------------

Q116:怎样自一个连结串列/杂凑表等等里面,插入/存取/改变元素?

Q117:「样版」(template)的用意是什麽?

Q118:"functiontemplate"的语法/语意是什麽?

Q119:"classtemplate"的语法/语意是什麽?

Q120:什麽是「参数化型别」(parameterizedtype)?

Q121:「泛型」(genericity)是什麽?

第20节:程式库

----------------

Q122:怎样拿到"STL"?

Q123:怎样ftp到"NumericalRecipes"附的程式?

Q124:为什麽我的执行档会这麽大?

第21节:特定系统的细节

------------------------

Q125:GNUC++(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:为什麽浮点数(floatingpoint)这麽不精确?为什麽这段程式不会印出0.43?

⊙22B:其他环境下的琐事

Q134:有任何TeX或LaTeX的巨集,能处理"C++"的留白效果(spacing)吗?

Q135:在哪儿可拿到C++2LaTeX这个C++原始码的LaTeX美编工具(pretty

printer)?

Q136:该到哪里取得"tgrind"这个C++/C/etc的原始码美编工具?

Q137:有给GNUemacs编辑器用的C++-mode吗?有的话,该怎麽拿?

Q138:我要到哪儿得到和作业系统相关的FAQs(譬如:BC++、DOS、Windows等等)?

Q139:为什麽我的DOSC++程式说"Sorry:floatingpointcodenotlinked"

“抱歉,浮点运算程式码未连结进来”?

Q140:为什麽当我没执行BC45IDE的话,BC++做出来的Windows应用程式就不能用?

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

●1C:术语及常用的缩写

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

这儿是一些此文件所采用的缩写:

字汇意义

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

fnfunction,函数(单数型)

fnsfunctions,函数(复数型)

paramparameter,参数

ptrpointer,指标,C/C++的语法元素,宣告法:int*p;

refreference,参考,C++的语法元素,宣告法:int&r;

OOobject-oriented,物件导向

OOPobject-orientedprogramming,物件导向程式设计

OOPLobject-orientedprogramminglanguage,物件导向语言

method运作行为,"memberfunction成员函数"的另一种说法

【译注】"method"是源自Smalltalk的术语,很常用於OO界。

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

■□第2节:我该如何参与讨论?(发信之前请务必一读)

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

Q1:我该在哪个讨论区中发问?

Comp.lang.c++是讨论C++语言本身最好的地方(譬如:C++程式设计、语法、风格

)。其他讨论区是用来讨论特定的系统(譬如:MSWindows或是UNIX),或是其他

和C++语言不直接相关的主题(譬如:怎样使用你的编译器)。底下列出一些非常热

门的讨论区,并从它们的FAQs中摘录些片断,应该能让您明了它们最常讨论哪些课

题。

comp.os.ms-windows.programmer.tools

此区是用来讨论有关Windows软体发展系统工具的选择及使用。

comp.os.ms-windows.programmer.misc

此乃论及其馀Windows软体发展之事项。

[有个FAQ列表,列出所有comp.os.ms-windows.programmer.*讨论区]

FAQ5.7.1.在DLL中存取C++的物件类别

FAQ6.1.1.以MDI子视窗做出对话框[用OWL]

FAQ6.2.1.把禁能的选项致能起来[用MFC]

FAQ8.1.5.使用windows.h的STRICT符号定义

FAQ10.程式设计参考资料

comp.os.msdos.programmer

许多信件都是关於程式语言产品的(主要是Borland和Microsoft)。

FAQ301.怎样才能读取字元而不[等待]Enter键?

FAQ412.怎样读取、建立、更改及删除磁片标名?

FAQ504.怎样设定COM埠,以用它来传输资料?

FAQ602.C程式怎样才能送控制码给印表机?

FAQ606.怎样才能得知Microsoft滑鼠的位置及按钮状态?

FAQ707.怎样写常驻程式(TSR)工具?

FAQB0.怎样连系[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

FAQ4.5)怎样使用popen()开启行程以读写之?

FAQ4.6)怎样在C程式里sleep()一秒以内?

comp.unix.solaris(包含SunOS4.x和Solaris)

FAQ4)Signal入门

FAQ5)等待子行程Exit

gnu.g++.help

FAQ:到哪里找C++的demangler(反签名编码器)?

FAQ:哪里有Solaris2.x版的gcc/g++位元档?

FAQ:有g++2.x的文件吗?

gnu.g++.bug[g++的臭□列表--请见g++的文件]

comp.lang.c

FAQ1.10:我搞糊涂了。NULL保证一定是0,但是null指标却不是?

FAQ2.3:那麽,在C里头「指标和阵列等价」是什麽意思?

FAQ4.2:[为什麽"printf("%d\n,"i++*i++);"有问题?]

FAQ7.1:怎样写一个接收不定数目引数的函数?[stdarg.h或是varargs.h]

FAQ10.4:怎麽宣告一个指向某种函数的指标阵列,而该函数的传回值为:

指向另一个传回字元指标的函数?

并请参考看看comp.graphics、comp.sources.wanted、comp.programming,以及

comp.object(它的FAQ是个很棒的OOP入门、术语观念概论文件)。请记住:

comp.std.c++是专门讨论和研议中的ANSI/ISOC++标准方案(下文会提)“直接

”相关的事项。

同时到上述信区和comp.lang.c++去问同一个问题,几乎是没必要的(你是知道的

,特定系统信区的读者不用机器语言写程式)。只因你的问题「真的很要紧」,就到

处发问,是个很坏的习惯。如果你在「正确的」信区没得到回音,且认为你非得在这

儿发信不可,请至少考虑一下,将这儿的回信重导回原来那个适当的信区。

在任何信区发问之前,你应当先读读它的FAQ。你想问的可能就在上面,这样就可省

下你发信的时间,以及全世界数以千计的人类读你的信的时间。回答已经是FAQ问题

的人,可能会因为白白浪费时间而烦扰不已;他们也可能会给你错误或不完整的解答

,因为他们也没看过FAQ。

「常见问题解答」文件每天24小时都可由anonymousftp(rtfm.mit.edu的

/pub/usenet/comp.what.ever)或是e-mailserver(寄一则内容为"help"的信到

mail-server@rtfm.mit.edu)来取得。欲知详情,请见"Introductiontothe

*.answersnewsgroups"这份文件,它在news.answers或news.announce.newusers

(这儿还有许多必须一读的文件)中找到。

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

Q2:我该怎麽提出「我的程式有毛病」的问题呢?

底下是一些建议,让comp.lang.c++的读者能帮你解决程式设计的问题。

1.请读读上一个问题,以确定你的问题是针对C++语言本身,而和你的程式设计系

统(譬如:绘图、印表机、设备……)或是编译环境(譬如:「整合环境挂了」

、「怎样消除xxxx警告讯息」、「怎样连结程式库」)完全无关。如果你想知道

为什麽你OWL程式中的虚拟函数CmOk()没被呼叫到,你的问题可能比较适合放

在Windows程式设计的信区。如果你能写个独立的小程式,而它会让编译器产生

和你那个OWL程式同样的错误讯息或行为的话,就可以放到comp.lang.c++了,

其他系统的C++程式员可能帮得上忙。

2.「信件标题」栏位要有意义。像是「C++程式」这样的标题太空泛了,「new一

个多维阵列的问题」就很好。不要用一堆惊叹号,穷嚷嚷著「救命啊」,或是开

玩笑的用「SEXSEXSEX」这种标题。如果你认为该问题和你的编译器有关,最好

在标题栏中道出编译器和版本编号。

3.列出完整的、可编译得过去的程式码。要从人类的语言叙述里,去除错或是重建

回一个程式,是极为困难的事。「完整的程式码」指的是:任何被用到的型别、

函数都要宣告出来,被用到的标头档都要#include进来……等等。请将程式码

裁减到只留必要的部份,我们并不需要那些执行起来(甚至连结时)“有用的”

东西,我们只须能重现出你的错误讯息(可能在不同的编译器中)就行了。「可

编译得过去」指的是:不要含有一堆未注解掉的...这种删节号,或是各行行首

的行号:

14:#include

15:classFoo{...};//像这样就是很讨人厌的东西!

将你的程式组织成线性结构,不要让我们再切割、制造些标头档案。请仔细输入

你的程式码--我们通常不容易判断:某个地方只是你的打字错误,抑或它真的

就是你的问题所在。尽量改用编辑器的「剪贴」或「插入档案」功能。

4.列出你用的编译器、编译器版本,以及你使用的系统。我知道我刚刚说过:特定

系统的问题要去特定的信区发问,但和编译器有关的资讯,常常对侦查问题有帮

助(「喔,我记得Acme1.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)资料来办到,以避免其他模组存取

到它。

「多重案例multipleinstances」:典型的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个元素……等等)。你甚至可以做出个“聪明的指标”(smartpointer),以指

向磁碟或其他地方去("x=*p"可dereference[解参用]指标,也就可以在磁碟

中找到p所“指到”的地方,并传回其值)。这可让使用者以切近该问题的方式来

写程式,而非以机器的语言来解题。

【译注】STL(StandardTemplateLibrary)就大量利用到「聪明的指标」功能。

「继承性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)与动态系

结(dynamicbinding)最容易从实例来理解了,所以我提个典型的例子:绘图软体

得处理圆形、方形、矩形、多边形及直线,这些都是「形状shape」。大部份绘图软

体的内部函数都需要个“形状”的参数(相对於某些像是“方形”这种特定的形状)

,譬如:当我们用滑鼠选取某个图形,它就可能被拖曳放到萤幕某处。多型和动态系

结让程式能正确运作,即使编译器只知道该参数是个「形状」,而不知它到底是什麽

形状。我们再假设刚才提到的"pick_and_drag(Shape*)"函数於星期二编译好了,

到了星期三,你打算再加个六边形。听起来很奇怪,但pick_and_drag()仍然能够

处理这个六边形,即使当pick_and_drag()编译时六边形还不存在!(若你明了

C++是怎麽做的,它就再也不惊异了--但它仍然是很方便的!)

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

Q5:谁在用C++?

很多很多的公司及政府部门。相当的多。

统计上来看:当你正在读这份FAQ文字时,就有5个人正成为C++的程式员。

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

Q6:有任何C++标准化方案在进行吗?

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

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

这些人:

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

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

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

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

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

ISOCommitteeDraftforC++以及ANSIC++Draft(将要供publicreview的文

件)可如此取得:

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

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

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

也能拿到HTML和ASCII的版本:

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

也能拿到书面版本:

X3Secretariat

1250EyeStreetNW

Suite200

Washington,DC20005

202-626-5738

你也可以用email:

lbarra@itic.nw.dc.us(LynnBarra)

注明要索取最新的"DraftProposedAmericanNationalStandardforInformation

Systems--ProgrammingLanguageC++",文件编号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"字("typedefstructFredFred"这种技巧仍然能

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

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

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

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

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

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

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

若没有个“好的”通用型C++物件程式库,则会耗时更久。想成为顾问级的高手,则

约需3年。

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

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

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

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

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

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

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

Q10:什麽是类别(class)?

物件导向系统的基石。

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

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

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

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

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

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

struct。

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

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

Q11:什麽是物件(object)?

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

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

件」通常意指「类别的案例(aninstanceofaclass)」,因此类别定义了数个物

件(案例)的行为。

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

Q12:什麽是参考(reference)?

一个物件的“别名”(alias,另一个名称)。

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

voidswap(int&i,int&j)

{

inttmp=i;

i=j;

j=tmp;

}

main()

{

intx,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++经验後,会发现这正是一种「资讯隐藏」的作法,是利

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

题。

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

Q16:行内函数是做什麽的?

行内函数(inlinefunction)是个程式码会塞入呼叫者所在之处的函数。就像巨集

一样,行内函数免除了函数呼叫的额外负担,以增进效率,并且(尤其是!)还能让

编译器对它施以最佳化(程序融合"proceduralintegration")。不过和巨集不同

的是:它只会对所有引数求一次的值(在语意上,该“函数呼叫”和正常函数一样,

只是比较快速罢了),以避免某些不易察觉的巨集错误。此外,它还会检测引数的型

态,做必要的型别转换(巨集对你有害;除非绝对必要,否则别再用它了)。

注意:过度使用行内函数会让程式码肥胖,於分页(paging)环境下反而有负面的性

能影响。

宣告法:在函数定义处使用"inline"关键字:

inlinevoidf(inti,charc){/*...*/}

或者是在类别内将定义包括进去:

classFred{

public:

voidf(inti,charc){/*...*/}

};

或是在类别外头,以"inline"来定义该成员函数:

classFred{

public:

voidf(inti,charc);

};

inlinevoidFred::f(inti,charc){/*...*/}

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

■□第5节:建构子和解构子

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

Q17:建构子(constructor)是做什麽的?

建构子乃用来从零开始建立物件。

建构子就像个「初始化函数」;它把一堆散乱的位元组成一个活生生的物件。最低限

度它会初始化内部用到的栏位,也可能会配置所须的资源(记忆体、档案、semaphore

、socket等等)。

"ctor"是建构子constructor最常见的缩写。

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

Q18:怎样才能让建构子呼叫另一个同处一室的建构子?

没有办法。

原因是:如果你呼叫另一个建构子,编译器会初始化一个暂时的区域性物件;但并没

有初始化“这个”你想要的物件。你可以用预设参数(defaultparameter),将两

个建构子合并起来,或是在私有的"init()"成员函数中共享它们的程式码。

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

Q19:解构子(destructor)是做什麽的?

解构子乃物件之葬礼。

解构子是用来释放该物件所配置到的资源,譬如:Lock类别可能会锁住一个

semaphore,解构子则用来释放它。最常见的例子是:当建构子用了"new"以後,解

构子用"delete"。

解构子是个「去死吧」的运作行为(method),通常缩写为"dtor"。

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

■□第6节:运算子多载

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

Q20:运算子多载(operatoroverloading)是做什麽的?

它可让使用类别的人以直觉来操作之。

运算子多载让C/C++的运算子,能对自订的型态(物件类别)赋予自订的意义。它

们形同是函数呼叫的语法糖衣(syntacticsugar):

classFred{

public:

//...

};

#if0

Fredadd(Fred,Fred);//没有运算子多载

Fredmul(Fred,Fred);

#else

Fredoperator+(Fred,Fred);//有运算子多载

Fredoperator*(Fred,Fred);

#endif

Fredf(Freda,Fredb,Fredc)

{

#if0

returnadd(add(mul(a,b),mul(b,c)),mul(c,a));//没有...

#else

returna*b+b*c+c*a;//有...

#endif

}

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

Q21:哪些运算子可以/不能被多载?

大部份都可以被多载。

不能的C运算子有"."和"?:"(和以技术上来说,可算是运算子的"sizeof")。

C++增加了些自己的运算子,其中除了"::"和".*".之外都可以被多载。

底下是个足标(subscript)运算子的例子(它会传回一个参考)。最前面是“不用

”多载的:

classArray{

public:

#if0

int&elem(unsignedi){if(i>99)error();returndata[i];}

#else

int&operator[](unsignedi){if(i>99)error();returndata[i];}

#endif

private:

intdata[100];

};

main()

{

Arraya;

#if0

a.elem(10)=42;

a.elem(12)+=a.elem(13);

#else

a[10]=42;

a[12]+=a[13];

#endif

}

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

Q22:怎样做一个"**"「次方」运算子?

无解。

运算子的名称、优先序、结合律以及元数(arity)都被语言所定死了。C++里没有

"**"运算子,所以你无法替类别订做一个它。

还怀疑的话,考虑看看"x**y"和"x*(*y)",这两者是完全一样的(换句话说

,编译器会假设"y"是个指标)。此外,运算子多载只是函数呼叫的语法糖衣而已

,虽然甜甜的,但本质上并未增加什麽东西。我建议你多载"pow(base,exponent)"

这个函数(它的倍精确度版本在中)。

附带一提:operator^可以用,但它的优先序及结合律不符「次方」所需。

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

■□第7节:夥伴

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

Q23:夥伴(friend)是什麽?

让别的类别或函数能存取到你的类别内部的东西。

夥伴可以是函数或其他类别。类别会对它的夥伴开放存取权限。正常情况下,程式员

会下意识、技术性地控制该类别的夥伴与运作行为(否则当你想更动类别时,还得先

有其他部份的拥有者之同意才行)。

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

Q24:「夥伴」违反了封装性吗?

若善用之,反而会「强化」封装性。

我们经常得将一个类别切成两半,当这两半各有不同的案例个数及生命期时。在此情

形之下,它们通常需要直接存取对方的内部(这两半“本来”是在同一个类别里面,

所以你并未“增加”存取资料结构的运作行为个数;你只是在“搬动”这些运作行为

所在之处而已)。最安全的实作方式,就是让这两半互为彼此的「夥伴」。

若你如上述般的使用夥伴,你依然是将私有的东西保持在私有的状态。遇到上述的情

况,如果还呆呆的想避免使用夥伴关系,许多人不是采用公共资料(糟透了!),就

是弄个公共的get/set存取运作行为来存取彼此的资料,事实上这些都破坏了封装

性。只有在类别的外面该私有资料「仍有其意义」(以使用者的角度来看)时,开放

出私有资料的存取运作行为才称得上是恰当的做法。多数情况下,「存取运作行为」

就和「公共资料」一样糟糕:它们对私有资料成员只隐其“名”而已,却未隐藏其“

存在”。

同样的,如果将「夥伴函数」做为另一种类别公共存取函数的语法,那就和违反封装

性的成员函数一样破坏了封装。换句话说,物件类别的夥伴及成员都是「封装的界线

」,如同「类别定义」本身一样。

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

Q25:夥伴函数的优缺点?

它提供了某种介面设计上的自由。

成员函数和夥伴函数都有同等的存取特权(100%的权利),主要的差别在於:夥伴

函数用起来像是"f(x)",而成员函数则是"x.f()"。因此,夥伴函数可让物件类别

设计者挑选他看得最顺眼的语法,以降低维护成本。

夥伴函数主要的缺点在於:当你想做动态系结(dynamicbinding)时,它需要额外

的程式码。想做出「虚拟夥伴」的效果,该夥伴函数应该呼叫个隐藏的(通常是放在

"protected:"里)虚拟成员函数;像这个样子:"voidf(Base&b){b.do_f();}"

。衍生类别会覆盖(override)掉那个隐藏的成员函数("voidDerived::do_f()")

,而不是该夥伴函数。

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

Q26:「夥伴关系无继承及递移性」是什麽意思?

夥伴关系的特权性无法被继承下来:夥伴的衍生类别不必然还是夥伴(我把你当朋友

,但这不代表我也一定会信任你的孩子)。如果"Base"类别宣告了"f()"为它的

夥伴,"f()"并不会自动对由"Base"衍生出来的"Derived"类别所多出来的部份

拥有特殊的存取权力。

夥伴关系的特权无递移性:夥伴类别的夥伴不必然还是原类别的夥伴(朋友的朋友不

一定也是朋友)。譬如,如果"Fred"类别宣告了"Wilma"类别为它的夥伴,而且

"Wilma"类别宣告了"f()"为它的夥伴,则"f()"不见得对"Fred"有特殊的存取

权力。

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

Q27:应该替类别宣告个成员函数,还是夥伴函数?

可能的话,用成员函数;必要时,就用夥伴。

有时在语法上来看,夥伴比较好(譬如:在"Fred"类别中,夥伴函数可把"Fred"

弄成是第二个参数,但在成员函数中则一定得放在第一个)。另一个好例子是:二元

中序式算数运算子(譬如:"aComplex+aComplex"可能应该定义成夥伴而非成员函

数,因为你想让"aFloat+aComplex"这种写法也能成立;回想一下:成员函数无

法提升它左侧的参数,因为那样会把引发该成员函数的物件所属之类别给改变掉)。

在其他情况下,请选成员函数而不要用夥伴函数。

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

■□第8节:输入/输出:和

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

Q28:该怎样替"classFred"提供输出功能?

用夥伴函数operator<<:

classFred{

public:

friendostream&operator<<(ostream&o,constFred&fred)

{returno<<fred.i;}

//...

private:

inti;//只为了说明起见而设的

};

我们用夥伴而不用成员函数,因为"Fred"是第二个参数而非第一个。输入的功能亦

类似,只是要改写成:

istream&operator>>(istream&i,Fred&fred);

//^^^^^-------不是"constFred&fred"!

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

Q29:为什麽我该用而不是以前的?

增加型别安全、减少错误、增进效率、有延展性、提供衍生能力。

Printf还好,而scanf除了容易写错之外也还算可以,然而和C++的I/O系统相

比,它们都有其限制。C++的I/O(用"<<"及">>"),和C("printf()"和

"scanf()")相比:

*型别安全--要做I/O的物件,编译器会静态地事先得知其型别,而不是动态地

由"%"一栏查知。

*不易出错--冗馀的资讯会增加错误的机会。C++的I/O就不需要多馀的"%"。

*更快速--printf是个小型语言的「解译器」,该语言主要是由"%"这种东西

构成的;在执行期它用这些栏位来选择正确的格式化方式。C++的I/O系统则是

静态的依各引数真正的型别来挑选副程式,以增进执行效率。

*延展性--C++I/O机制可在不改动原有程式码的情况下,就加进使用者新设计

的型态(能想像如果大家同时把互不相容的"%"栏位塞入printf和scanf,会

是怎样的混乱场面?!)。

*可衍生(subclassable)--ostream和istream(C++的FILE*代替品)都是

真正的类别,因此可以被衍生下去。这意味著:你可以让其他自定的东西有著和

stream雷同的外表与行为,但实际上做的却是你想做的特定事情。你自动就重用

了数以万计别人(你甚至不认识它们)写好的I/O程式码,而他们也不需要知道

你所做的「延伸stream」类别。

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

Q30:为什麽我处理输入时,会超过档案的结尾?

因为eof(档案结尾)的状态,是到「将要超过档案结尾的动作」才会被设定。也就

是说,读档案的最後一个位元组并不会设定eof的状态。

【译注】这也是C常见的错误。

如果你的程式像这样:

inti=0;

while(!cin.eof()){

cin>>x;

++i;

//workwithx

}

你的i变数就会多了一。

你真正该做的是这样:

inti;

while(cin>>x){

++i;

//workwithx

}

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

Q31:为什麽我的程式执行完第一次回圈後,会对输入的要求不加理睬?

因为读取数值的程式,把非数字的字元留在输入缓冲区(inputbuffer)里头了。

【译注】这也是C,甚至Pascal常见的错误。

如果你的程式如下:

charname[1000];

intage;

for(;;){

cout<<"Name:";

cin>>name;

cout<<"Age:";

cin>>age;

}

你应该这样写:

for(;;){

cout<<"Name:";

cin>>name;

cout<<"Age:";

cin>>age;

cin.ignore(INT_MAX,'\n');

}

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

Q32:在DOS及OS/2的binary模式下,要怎样来"reopen"cin及cout?

有这个问题,最典型的情况就是:有人想对cin、cout做binary的I/O,但是作

业系统(像是DOS或OS/2)却总是会做CR-LF的转换动作。

解决法:cin、cout、cerr这些事先定义好的串流,都是text的串流,没有标准做

法能把它们弄成binary模式。把串流关掉再设法以binary模式reopen它们,可

能会导致不可预期的结果。

在这两种模式有不同行为的系统上,一定有办法让它们变成binary串流,但是你得

去查查该系统的文件。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有