C++語言常見問題解答(1) (轉)
C++語言常見問題解答(1) (轉)[@more@]C++語言常見問題解答(1) 中譯者:葉秉哲 (2001-04-27 13:05:08)
=======================================
(US comp.lang.c++ 的 FAQ 中譯)
原作者:Marshall Cline (cline@cheetah.ece.clarkson.edu)
(cline@parashift.com)
中譯者:葉秉哲 (william@tiger.cis.nctu.edu.tw)
原檔案:USENET comp.lang.c++ FAQ, Jan 31, 1996.
版權宣告:完全依照原作者 Marshall Cline 於此檔案中所示之版權事項
(請見下文之 "COPYRIGHT" 部份)。
如欲對本中譯檔案作授權事項之外的處理,請先洽本譯者。
責任事項:完全比照原作者 Marshall Cline 於此檔案中所示之宣告事項
(請見下文之 "NO WARRANTY" 部份)。
中譯事項:筆者雖盡力使此中譯檔案合乎信、達的要求,但仍恐有未逮之處,
故有任何出入之處,請以原文為準。
任何筆者為中譯、詮釋所需而加註的地方,都以 【譯註】 符號
標示出來。
本譯文位置:以 URL (Uniform Re Locator) 格式說明。
:
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 釋出。
本檔案中譯的授權:
--- --- --- --- --- Quote Begin --- --- --- --- ---
From cline@cheetah.ece.clarkson.edu Mon Oct 10 11:56:59 1994
Return-Path:
Received: from cheetah.ece.clarkson.edu by cis.nctu.edu.tw (4.1/SMI-4.1)
id AA18895; Mon, 10 Oct 94 11:56:46 CST
Received: by cheetah.ece.clarkson.edu (4.1/SMI-4.1)
id AA06374; Sun, 9 Oct 94 23:59:49 EDT
Date: Sun, 9 Oct 94 23:59:49 EDT
From: cline@cheetah.ece.clarkson.edu (Marshall Cline)
Message-Id: <9410100359.AA06374@cheetah.ece.clarkson.edu>
To: is80001@cis.nctu.edu.tw
In-Reply-To: William Yeh's message of Sat, 24 Sep 94 10:31:48 CST
<9409240231.AA20537@cissun51.cis.nctu.edu.tw>
Subject: "C++ FAQ" book from Addison-Wesley
Reply-To: cline@sun.soe.clarkson.edu (Marshall Cline)
Status: OR
>Date: Sat, 24 Sep 94 10:31:48 CST
>From: is80001@cis.nctu.edu.tw (William Yeh)
>Newsgroups: comp.lang.c++
>X-Newsreader: TIN [version 1.2 PL2]
>
>Hi,
>
> We, students at Department of Computer & Information Science, enjoy
>your electronic-formed C++ FAQ very much. We'd like to translate it
>into our native Chinese for those having difficulty to read English
>articles.
>
> The translated article is meant to be used as an electronic document
>on Internet, and not for commercial use. We, therefore, ask for your
>grants for this translation.
>
> Regards.
>
>student at cis.nctu.edu.tw
>--
>-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> William Yeh | E- address:
> | is80001@cis.nctu.edu.tw
> Dept. of Computer & Info. Science | u8023001@cc.nctu.edu.tw
> National Chiao-Tung University, | william.bbs@bbs.cis.nctu.edu.tw
> Hsinchu, Taiwan, R.O.C. |
>-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
That sounds like a wonderful a.
Pession granted.
M.
--- --- --- --- --- Quote End --- --- --- --- ---
【中譯對照表】
底下列出本文出現的專有名詞、其他重要的詞兒,與譯者採用的中譯,視上下
文情況,它們也可能會有兩種以上的譯名。可能的話,括號中也會附上一些其
他書籍文章中常見的譯法。
abstraction 抽象化.
access 存取.
access function 存取.
alias 別名.
argument 引數.
arity 元數.
assignment 設定.
associativity 結合律.
base class 基底類別.
binding 繫結.
call 呼叫.
class 類別、物件類別.
composition 成份、零件.
constructor 建構子(建構元).
container 容器.
container class 容器類別.
data member 資料成員.
declaration 宣告 .
declare 宣告 .
default 預設、內定.
define 定義 .
definition 定義 .
dereference 解參用、解參考.
derive 衍生.
destructor 解構子(解構元).
dispatch 分派、函式分派.
dynamic 動態.
encapsulation 封裝、封裝性.
exception 例外、例外狀況(異常).
exception handling 例外處理.
explicit 明顯的、外顯的 .
expression 運算式.
friend 夥伴.
function 函式.
genericity 泛型.
header file 標頭檔(引入檔、含括檔).
hide 遮蔽.
hierarchy 階層.
identity 個體識別.
implement 實作 .
implementation 實作 .
inherit 繼承 .
inheritance 繼承 .
inline 行內(列內、內嵌).
inspector 查詢子.
instance 案例、實體(個體).
instantiate 案例化、實體化 .
instantiation 案例 .
key 關鍵字、保留字.
mangle 簽名編碼 .
mangling 簽名編碼 .
member 成員.
member function 成員函式.
member 成員物件.
method 運作方法、運算方法.
module 模組.
multiple inheritance 多重繼承.
mutator 更動子.
object 物件(個體).
OO 物件導向(個體導向).
物件導向程式設計.
operator 運運算元.
overload 多載(過荷、負載) .
overloading 多載(過荷、負載) .
override 覆蓋、改寫.
parameter 引數.
persistence 持續性(永續性、持固性) .
persistent object 持續性物件.
pointer 指標.
polymorphism 多型(同名異式).
precedence 優先序.
pretty printer 美編工具.
private 私有.
protected 保護.
原型、函式原型(雛型).
public 公共、公有.
pure virtual function 純虛擬函式.
reference 參考、參考值.
relation 關係.
return value 傳回值.
semantics 語意.
signature 簽名、型態簽名.
smart pointer 聰明的指標.
specialization 特異化、特殊化.
statement 陳述、指令(指述).
static 靜態.
structure 結構、記錄.
subclass 子類別、子代類別.
subtype 子型別、子型態.
superclass 父類別、親代類別.
syntax 語法、文法.
template 樣版(模版).
throw 丟出.
type 型態、型別.
virtual 虛擬.
virtual function 虛擬函式.
【中譯版本異動紀錄】
85.02. 對整篇譯文做比較多一點的修飾。
84.05. 修飾些 method 相關的譯名。
84.03. 修飾些 persistence、instance 相關的譯名。
84.01. 一些譯文修飾、增加此中譯檔案的 ftp 棲身處說明。
將覆蓋 (override) 與遮蔽 (hide) 二詞更明顯地區分開來。
對「聰明的指標」(smart pointer) 加一點詮釋。
83.12. 一些譯文修飾、將 "method" 統一譯為「運算方法」。
83.11. 第一次釋出,原載於交大資科系刊「資訊人園地」。
底下就是此 USENET comp.lang.C++ FAQ 檔案的正文。
== Part 1/4 ============================
【譯註】原檔案因篇幅過長,在釋出時就已分成四份。
comp.lang.c++ Frequently Asked Questions list (with answers, fortunately).
Copyright (C) 1991-96 Marshall P. Cline, Ph.D.
Posting 1 of 4.
1/96 :
* 關於恢復 fron.soe.clarkson.edu 的 anonymous ftp 方式仍無下文。
* 本月份沒什麼變動。
9/95 更新:
* 加入 FAQ 41:以變數做為多維陣列的第一維度。
* 加入 FAQ 123:關於 "Numerical Recipes" 的程式。
* 加入第 20 節 ("程式庫")。內容還很少,但總是個開端。
* 修正 FAQ 30 的錯誤(少了 "i" 變數)。
* 加入 FAQ 124:使用動態連結以避免過於龐大的執行檔。
* 加入 FAQ 32:想在 binary 下 "reopen" cin 及 cout 的問題。
* 加入 ftp ANSI/ISO Committee Draft 的資訊 (FAQ 7)。
7/95 更新:
* 小地方(除了下面會提到的 FTP 地點的變動之外)。
6/95 更新:
* 更正訂閱 ANSI-C++ Draft 的電子郵遞信箱。
* 新增關於浮點運算的 FAQ [Phil Staite 所提的]。
* 新增關於多維陣列的 FAQ [Doug Shapter 所提的]。
* 新增關於中斷服務常式 (ISR),以及指向成員函式的指標之 FAQ。
* 重排關於「用 'new' 來某些類別的物件」FAQ 的位置。
5/95 更新:
* 一些語句修飾。
4/95 更新:
* 新增 BC++ 方面常見的問題。
* 更改 NIHCL 的 ftp 位址。
* 新增解釋:"ARM" 代表 "Annotated Reference Manual"。
3/95 更新:
* 新增關於 "delete this" 的問題。
* 新增兩則關於 iostreams 與 eof 的問題。
* 更正些 emacs 的 "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-Questions for comp.lang.c++
REVISION: Jan 31, 1996
檔案不等於書本:這份 C++ FAQ 檔案和「FAQ 書」是不一樣的。“FAQ 書”
("C++ FAQs", Addison-Wesley, 1995) 是這篇檔案的五倍大。
底下有更詳細的介紹。
AUTHOR: Marshall P. Cline, Ph.D.
Paradigm Shift, Inc.
One Park St. / Norwood, NY 13668
voice: 315-353-6100
fax: 315-353-6110
: cline@parashift.com
COPYRIGHT: Copyright (C), 1991-96 Marshall P. Cline, Ph.D.
Permission to copy all or part of this work is granted,
provided that the copies are not made or distributed
for resale (except a nominal copy fee may be charged),
and provided that the AUTHOR, COPYRIGHT, & NO WARRANTY
sections are retained verbatim and are displayed
conspicuously. If anyone needs other permissions that
aren't covered by the above, please contact the author.
NO WARRANTY: THIS WORK IS PROVIDED ON AN "AS IS" BASIS. THE AUTHOR
PROVIDES NO WARRANTY WHATSOEVER, EITHER EXPRESS OR
IMPLIED, REGARDING THE WORK, INCLUDING WARRANTIES WITH
RESPECT TO ITS MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
版權宣告:Copyright (C), 1991-96 Marshall P. Cline, Ph.D.
複製本檔案全部或部份的內容,若合乎下述諸項要求,則允許之
:不得為轉售之目的而製作或傳播任何複製品(但可索取名義上
的傳播手續費),並且作者欄、版權宣告及責任事項的部份,要
一字不漏地、醒目地顯示出來。若您需要此處未提及的授權事項
,請洽本作者。
責任事項:這份檔案是供您參考用的。對於本作品可能造成的營利性、或任
何特殊場合適用性之保障,作者概不負責,不論是否曾明白地指
出或暗示。
【譯註】上述的「版權宣告」與「責任事項」譯文,僅供參考,一切請以
原文為準。譯者對它們亦概不負責…… ;->
檔案取得方法: 舊的 FTP 地點不能用了。我正在尋找新的地點,
請密切注意下個月的這個地方。
請不要寄信來推薦新的地點(我的信箱會爆滿的 :)
【譯註】臺灣使用者,請到以下地點,或其 AFS client 取得:
ftp://NCTUCCCA.edu.tw/USENET/FAQ/comp/lang/c++/FAQ*
其他資訊:comp.lang.c FAQ 每個月都會出現在該討論區中,
該檔案的維護者是 Steve Summit (scs@eskimo.com) 。
中文翻譯:用 "Big5" 內碼(在臺灣最廣為使用的 16 位元中文內碼)儲存
的中文譯文,可用 anonymous ftp 到以下地點取得:
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:運運算元多載(operator overloading)是做什麼的?
Q21:哪些運運算元可以/不能被多載?
Q22:怎樣做一個 "**"「次方」運運算元?
第7節:夥伴
------------
Q23:夥伴(friend)是什麼?
Q24:「夥伴」違反了封裝性嗎?
Q25:夥伴函式的優缺點?
Q26:「夥伴關係無繼承及遞移性」是什麼意思?
Q27:應該替類別宣告個成員函式,還是夥伴函式?
第8節:輸入/輸出: 和
---------------------------------------------
Q28:該怎樣替 "class Fred" 提供輸出功能?
Q29:為什麼我該用 而不是以前的 ?
Q30:為什麼我處理輸入時,會超過檔案的結尾?
Q31:為什麼我的程式執行完第一次迴圈後,會對輸入的要求不加理睬?
Q32:在 DOS 及 OS/2 的 binary 模式下,要怎樣來 "reopen" cin 及 cout?
========== POSTING #2 ==========
第9節:自由記憶體管理
----------------------
Q33:"delete p" 會刪去 "p" 指標,還是它指到的資料,"*p" ?
Q34:我能 "free()" 掉由 "new" 配置到的、"delete" 掉由 "malloc()" 配置到的
記憶體嗎?
Q35:為什麼該用 "new" 而不是老字號的 malloc() ?
Q36:為什麼 C++ 不替 "new" 及 "delete" 搭配個 "realloc()" ?
Q37:我該怎樣配置/釋放陣列?
Q38:萬一我忘了將 "[]" 用在 "delete" 由 "new Fred[n]" 配置到的陣列,會發生
什麼事?
Q39:成員函式做 "delete this" 的動作是合法的(並且是好的)嗎?
Q40:我該怎麼用 new 來配置多維陣列?
Q41:C++ 能不能做到在執行時期才指定陣列的長度?
Q42:怎樣確保某類別的物件都是用 "new" 建立的,而非區域或整體/靜態變數?
第10節:除錯與錯誤處理
------------------------
Q43:怎樣處理建構子的錯誤?
Q44:如果建構子會丟出例外的話,該怎麼處理它的資源?
第11節:Const 正確性
----------------------
Q45:什麼是 "const correctness"?
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) hides Base::f(float)" 是什麼意思?
⊙12B:繼承--一致性
Q60:我該遮蔽住由基底類別繼承來的公共成員函式嗎?
Q61:圓形 "Circle" 是一種橢圓 "Ellipse" 嗎?
Q62:對「圓形是/不是一種橢圓」這兩難問題,有沒有其他說法?
⊙12C:繼承--存取規則
Q63:為什麼衍生的類別無法存取基底的 "private" 東西?
Q64:"public:"、"private:"、"protected:" 的差別是?
Q65:當我改變了內部的東西,怎樣避免子類別被破壞?
⊙12D:繼承--建構子與解構子
Q66:若基底類別的建構子呼叫一個虛擬函式,為什麼衍生類別覆蓋掉的那個虛擬函
數卻不會被呼叫到?
Q67:衍生類別的解構子應該外顯地呼叫基底的解構子嗎?
⊙12E:繼承--Private 與 protected 繼承
Q68:該怎麼表達出「私有繼承」(private inheritance)?
Q69:「私有繼承」和「成份」(composition) 有多類似?
Q70:我比較該用哪一種:成份還是私有繼承?
Q71:我應該用指標轉型方法,把「私有」衍生類別轉成它的基底嗎?
Q72:保護繼承 (protected inheritance) 和私有繼承有何關連?
Q73:"private" 和 "protected" 的存取規則是什麼?
第13節:抽象化(abstraction)
-------------------------------
Q74:分離介面與實作是做什麼用的?
Q75:在 C++ 裡,我該怎樣分離介面與實作(像 Modula-2 那樣)?
Q76:ABC ("abstract base class") 是什麼?
Q77:「純虛擬」(pure virtual) 成員函式是什麼?
Q78:怎樣替整個類別階層提供列印的功能?
Q79:何時該把解構子弄成 virtual?
Q80:虛擬建構子 (virtual constructor) 是什麼?
========== 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:"inline virtual" 的成員函式真的會被 "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:怎樣把指向成員函式的指標傳給 signal handler、X event callback 等等?
Q113:當我想以成員函式做為中斷服務常式 (ISR) 時,為什麼產生(型態不
符)的錯誤?
Q114:為什麼我取不出 C++ 函式的位址?
Q115:怎樣宣告指向成員函式的指標陣列?
第19節:容器類別與 template
-----------------------------
Q116:怎樣自一個連結串列/雜湊表等等裡面,插入/存取/改變元素?
Q117:「樣版」(template)的用意是什麼?
Q118:"function template" 的語法/語意是什麼?
Q119:"class template" 的語法/語意是什麼?
Q120:什麼是「引數化型別」(parameterized 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 或是 ),或是其他
和 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 和 )。
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. (包含 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++. [g++ 的臭□列表 -- 請見 g++ 的檔案]
comp.lang.c
FAQ 1.10: 我搞糊塗了。NULL 保證一定是 0,但是 null 指標卻不是?
FAQ 2.3: 那麼,在 C 裡頭「指標和陣列等價」是什麼意思?
FAQ 4.2: [為什麼 "printf("%dn," 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) 或是 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++ 標準化方案在進行嗎?
有的;ANSI(美國的)和 ISO(國際的)組織正密切合作。ANSI-C++ 委員會稱為
"X3J16" ,而 ISO C++ 標準團體稱為 "WG21"。ANSI/ISO C++ 的標準過程中包含了
這些人:
AT&T, IBM, DEC, HP, Sun, MS, Borland, Zortech, Apple, O 等等等等。每次開
會約有 70 人,他們來自美、英、日、德、瑞典、丹麥、法國……(他們都有「區域
性」的委員會,派遣正式代表並主導「區域性」的會議)。
========================================
Q7:該到哪裡索取最新的 ANSI-C++ 標準草案?
ISO Committee Draft for C++ 以及 ANSI C++ Draft(將要供 public review 的文
件)可如此取得:
~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 s(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++經驗後,會發現這正是一種「資訊隱藏」的作法,是利
而非弊。好比說,程式員應該以切近該問題的方式來寫程式,而非以機器的語言來解
題。
========================================
Q16:行內函式是做什麼的?
行內函式(inline function)是個程式碼會塞入呼叫者所在之處的函式。就像巨集
一樣,行內函式免除了函式呼叫的額外負擔,以增進效率,並且(尤其是!)還能讓
編譯器對它施以最佳化(融合 "procedural integration")。不過和巨集不同
的是:它只會對所有引數求一次的值(在語意上,該“函式呼叫”和正常函式一樣,
只是比較罷了),以避免某些不易察覺的巨集錯誤。此外,它還會檢測引數的型
態,做必要的型別轉換(巨集對你有害;除非絕對必要,否則別再用它了)。
注意:過度使用行內函式會讓程式碼肥胖,於分頁(paging)環境下反而有負面的性
能影響。
宣告法:在函式定義處使用 "inline" 關鍵字:
inline void f(int i, char c) { /*...*/ }
或者是在類別內將定義包括進去:
class Fred {
public:
void f(int i, char c) { /*...*/ }
};
或是在類別外頭,以 "inline" 來定義該成員函式:
class Fred {
public:
void f(int i, char c);
};
inline void Fred::f(int i, char c) { /*...*/ }
=============================
■□ 第5節:建構子和解構子
=============================
Q17:建構子(constructor)是做什麼的?
建構子乃用來從零開始建立物件。
建構子就像個「初始化函式」;它把一堆散亂的位元組成一個活生生的物件。最低限
度它會初始化內部用到的欄位,也可能會配置所須的資源(記憶體、檔案、semaphore
、socket 等等)。
"ctor" 是建構子 constructor 最常見的縮寫。
========================================
Q18:怎樣才能讓建構子呼叫另一個同處一室的建構子?
沒有辦法。
原因是:如果你呼叫另一個建構子,編譯器會初始化一個暫時的區域性物件;但並沒
有初始化“這個”你想要的物件。你可以用預設引數(default parameter),將兩
個建構子合併起來,或是在私有的 "init()" 成員函式中共享它們的程式碼。
========================================
Q19:解構子(destructor)是做什麼的?
解構子乃物件之葬禮。
解構子是用來釋放該物件所配置到的資源,譬如:Lock 類別可能會鎖住一個
semaphore,解構子則用來釋放它。最常見的例子是:當建構子用了 "new" 以後,解
構子用 "delete"。
解構子是個「去死吧」的運作行為(method),通常縮寫為 "dtor"。
=========================
■□ 第6節:運運算元多載
=========================
Q20:運運算元多載(operator overloading)是做什麼的?
它可讓使用類別的人以直覺來操作之。
運運算元多載讓 C/C++ 的運運算元,能對自訂的型態(物件類別)賦予自訂的意義。它
們形同是函式呼叫的語法糖衣 (syntactic sugar):
class Fred {
public:
//...
};
#if 0
Fred add(Fred, Fred); //沒有運運算元多載
Fred mul(Fred, Fred);
#else
Fred operator+(Fred, Fred); //有運運算元多載
Fred operator*(Fred, Fred);
#endif
Fred f(Fred a, Fred b, Fred c)
{
#if 0
return add(add(mul(a,b), mul(b,c)), mul(c,a)); //沒有...
#else
return a*b + b*c + c*a; //有...
#endif
}
========================================
Q21:哪些運運算元可以/不能被多載?
大部份都可以被多載。
不能的 C 運運算元有 "." 和 "?:"(和以技術上來說,可算是運運算元的 "sizeof")。
C++ 增加了些自己的運運算元,其中除了 "::" 和 ".*". 之外都可以被多載。
底下是個足標(subscript)運運算元的例子(它會傳回一個參考)。最前面是“不用
”多載的:
class Array {
public:
#if 0
int& elem(unsigned i) { if (i>99) error(); return data[i]; }
#else
int& operator[] (unsigned i) { if (i>99) error(); return data[i]; }
#endif
private:
int data[100];
};
main()
{
Array a;
#if 0
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)"
這個函式(它的倍精確度版本在
=======================================
(US comp.lang.c++ 的 FAQ 中譯)
原作者:Marshall Cline (cline@cheetah.ece.clarkson.edu)
(cline@parashift.com)
中譯者:葉秉哲 (william@tiger.cis.nctu.edu.tw)
原檔案:USENET comp.lang.c++ FAQ, Jan 31, 1996.
版權宣告:完全依照原作者 Marshall Cline 於此檔案中所示之版權事項
(請見下文之 "COPYRIGHT" 部份)。
如欲對本中譯檔案作授權事項之外的處理,請先洽本譯者。
責任事項:完全比照原作者 Marshall Cline 於此檔案中所示之宣告事項
(請見下文之 "NO WARRANTY" 部份)。
中譯事項:筆者雖盡力使此中譯檔案合乎信、達的要求,但仍恐有未逮之處,
故有任何出入之處,請以原文為準。
任何筆者為中譯、詮釋所需而加註的地方,都以 【譯註】 符號
標示出來。
本譯文位置:以 URL (Uniform Re Locator) 格式說明。
:
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 釋出。
本檔案中譯的授權:
--- --- --- --- --- Quote Begin --- --- --- --- ---
From cline@cheetah.ece.clarkson.edu Mon Oct 10 11:56:59 1994
Return-Path:
Received: from cheetah.ece.clarkson.edu by cis.nctu.edu.tw (4.1/SMI-4.1)
id AA18895; Mon, 10 Oct 94 11:56:46 CST
Received: by cheetah.ece.clarkson.edu (4.1/SMI-4.1)
id AA06374; Sun, 9 Oct 94 23:59:49 EDT
Date: Sun, 9 Oct 94 23:59:49 EDT
From: cline@cheetah.ece.clarkson.edu (Marshall Cline)
Message-Id: <9410100359.AA06374@cheetah.ece.clarkson.edu>
To: is80001@cis.nctu.edu.tw
In-Reply-To: William Yeh's message of Sat, 24 Sep 94 10:31:48 CST
<9409240231.AA20537@cissun51.cis.nctu.edu.tw>
Subject: "C++ FAQ" book from Addison-Wesley
Reply-To: cline@sun.soe.clarkson.edu (Marshall Cline)
Status: OR
>Date: Sat, 24 Sep 94 10:31:48 CST
>From: is80001@cis.nctu.edu.tw (William Yeh)
>Newsgroups: comp.lang.c++
>X-Newsreader: TIN [version 1.2 PL2]
>
>Hi,
>
> We, students at Department of Computer & Information Science, enjoy
>your electronic-formed C++ FAQ very much. We'd like to translate it
>into our native Chinese for those having difficulty to read English
>articles.
>
> The translated article is meant to be used as an electronic document
>on Internet, and not for commercial use. We, therefore, ask for your
>grants for this translation.
>
> Regards.
>
>student at cis.nctu.edu.tw
>--
>-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> William Yeh | E- address:
> | is80001@cis.nctu.edu.tw
> Dept. of Computer & Info. Science | u8023001@cc.nctu.edu.tw
> National Chiao-Tung University, | william.bbs@bbs.cis.nctu.edu.tw
> Hsinchu, Taiwan, R.O.C. |
>-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
That sounds like a wonderful a.
Pession granted.
M.
--- --- --- --- --- Quote End --- --- --- --- ---
【中譯對照表】
底下列出本文出現的專有名詞、其他重要的詞兒,與譯者採用的中譯,視上下
文情況,它們也可能會有兩種以上的譯名。可能的話,括號中也會附上一些其
他書籍文章中常見的譯法。
abstraction 抽象化.
access 存取.
access function 存取.
alias 別名.
argument 引數.
arity 元數.
assignment 設定.
associativity 結合律.
base class 基底類別.
binding 繫結.
call 呼叫.
class 類別、物件類別.
composition 成份、零件.
constructor 建構子(建構元).
container 容器.
container class 容器類別.
data member 資料成員.
declaration 宣告 .
declare 宣告 .
default 預設、內定.
define 定義 .
definition 定義 .
dereference 解參用、解參考.
derive 衍生.
destructor 解構子(解構元).
dispatch 分派、函式分派.
dynamic 動態.
encapsulation 封裝、封裝性.
exception 例外、例外狀況(異常).
exception handling 例外處理.
explicit 明顯的、外顯的 .
expression 運算式.
friend 夥伴.
function 函式.
genericity 泛型.
header file 標頭檔(引入檔、含括檔).
hide 遮蔽.
hierarchy 階層.
identity 個體識別.
implement 實作 .
implementation 實作 .
inherit 繼承 .
inheritance 繼承 .
inline 行內(列內、內嵌).
inspector 查詢子.
instance 案例、實體(個體).
instantiate 案例化、實體化 .
instantiation 案例 .
key 關鍵字、保留字.
mangle 簽名編碼 .
mangling 簽名編碼 .
member 成員.
member function 成員函式.
member 成員物件.
method 運作方法、運算方法.
module 模組.
multiple inheritance 多重繼承.
mutator 更動子.
object 物件(個體).
OO 物件導向(個體導向).
物件導向程式設計.
operator 運運算元.
overload 多載(過荷、負載) .
overloading 多載(過荷、負載) .
override 覆蓋、改寫.
parameter 引數.
persistence 持續性(永續性、持固性) .
persistent object 持續性物件.
pointer 指標.
polymorphism 多型(同名異式).
precedence 優先序.
pretty printer 美編工具.
private 私有.
protected 保護.
原型、函式原型(雛型).
public 公共、公有.
pure virtual function 純虛擬函式.
reference 參考、參考值.
relation 關係.
return value 傳回值.
semantics 語意.
signature 簽名、型態簽名.
smart pointer 聰明的指標.
specialization 特異化、特殊化.
statement 陳述、指令(指述).
static 靜態.
structure 結構、記錄.
subclass 子類別、子代類別.
subtype 子型別、子型態.
superclass 父類別、親代類別.
syntax 語法、文法.
template 樣版(模版).
throw 丟出.
type 型態、型別.
virtual 虛擬.
virtual function 虛擬函式.
【中譯版本異動紀錄】
85.02. 對整篇譯文做比較多一點的修飾。
84.05. 修飾些 method 相關的譯名。
84.03. 修飾些 persistence、instance 相關的譯名。
84.01. 一些譯文修飾、增加此中譯檔案的 ftp 棲身處說明。
將覆蓋 (override) 與遮蔽 (hide) 二詞更明顯地區分開來。
對「聰明的指標」(smart pointer) 加一點詮釋。
83.12. 一些譯文修飾、將 "method" 統一譯為「運算方法」。
83.11. 第一次釋出,原載於交大資科系刊「資訊人園地」。
底下就是此 USENET comp.lang.C++ FAQ 檔案的正文。
== Part 1/4 ============================
【譯註】原檔案因篇幅過長,在釋出時就已分成四份。
comp.lang.c++ Frequently Asked Questions list (with answers, fortunately).
Copyright (C) 1991-96 Marshall P. Cline, Ph.D.
Posting 1 of 4.
1/96 :
* 關於恢復 fron.soe.clarkson.edu 的 anonymous ftp 方式仍無下文。
* 本月份沒什麼變動。
9/95 更新:
* 加入 FAQ 41:以變數做為多維陣列的第一維度。
* 加入 FAQ 123:關於 "Numerical Recipes" 的程式。
* 加入第 20 節 ("程式庫")。內容還很少,但總是個開端。
* 修正 FAQ 30 的錯誤(少了 "i" 變數)。
* 加入 FAQ 124:使用動態連結以避免過於龐大的執行檔。
* 加入 FAQ 32:想在 binary 下 "reopen" cin 及 cout 的問題。
* 加入 ftp ANSI/ISO Committee Draft 的資訊 (FAQ 7)。
7/95 更新:
* 小地方(除了下面會提到的 FTP 地點的變動之外)。
6/95 更新:
* 更正訂閱 ANSI-C++ Draft 的電子郵遞信箱。
* 新增關於浮點運算的 FAQ [Phil Staite 所提的]。
* 新增關於多維陣列的 FAQ [Doug Shapter 所提的]。
* 新增關於中斷服務常式 (ISR),以及指向成員函式的指標之 FAQ。
* 重排關於「用 'new' 來某些類別的物件」FAQ 的位置。
5/95 更新:
* 一些語句修飾。
4/95 更新:
* 新增 BC++ 方面常見的問題。
* 更改 NIHCL 的 ftp 位址。
* 新增解釋:"ARM" 代表 "Annotated Reference Manual"。
3/95 更新:
* 新增關於 "delete this" 的問題。
* 新增兩則關於 iostreams 與 eof 的問題。
* 更正些 emacs 的 "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-Questions for comp.lang.c++
REVISION: Jan 31, 1996
檔案不等於書本:這份 C++ FAQ 檔案和「FAQ 書」是不一樣的。“FAQ 書”
("C++ FAQs", Addison-Wesley, 1995) 是這篇檔案的五倍大。
底下有更詳細的介紹。
AUTHOR: Marshall P. Cline, Ph.D.
Paradigm Shift, Inc.
One Park St. / Norwood, NY 13668
voice: 315-353-6100
fax: 315-353-6110
: cline@parashift.com
COPYRIGHT: Copyright (C), 1991-96 Marshall P. Cline, Ph.D.
Permission to copy all or part of this work is granted,
provided that the copies are not made or distributed
for resale (except a nominal copy fee may be charged),
and provided that the AUTHOR, COPYRIGHT, & NO WARRANTY
sections are retained verbatim and are displayed
conspicuously. If anyone needs other permissions that
aren't covered by the above, please contact the author.
NO WARRANTY: THIS WORK IS PROVIDED ON AN "AS IS" BASIS. THE AUTHOR
PROVIDES NO WARRANTY WHATSOEVER, EITHER EXPRESS OR
IMPLIED, REGARDING THE WORK, INCLUDING WARRANTIES WITH
RESPECT TO ITS MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
版權宣告:Copyright (C), 1991-96 Marshall P. Cline, Ph.D.
複製本檔案全部或部份的內容,若合乎下述諸項要求,則允許之
:不得為轉售之目的而製作或傳播任何複製品(但可索取名義上
的傳播手續費),並且作者欄、版權宣告及責任事項的部份,要
一字不漏地、醒目地顯示出來。若您需要此處未提及的授權事項
,請洽本作者。
責任事項:這份檔案是供您參考用的。對於本作品可能造成的營利性、或任
何特殊場合適用性之保障,作者概不負責,不論是否曾明白地指
出或暗示。
【譯註】上述的「版權宣告」與「責任事項」譯文,僅供參考,一切請以
原文為準。譯者對它們亦概不負責…… ;->
檔案取得方法: 舊的 FTP 地點不能用了。我正在尋找新的地點,
請密切注意下個月的這個地方。
請不要寄信來推薦新的地點(我的信箱會爆滿的 :)
【譯註】臺灣使用者,請到以下地點,或其 AFS client 取得:
ftp://NCTUCCCA.edu.tw/USENET/FAQ/comp/lang/c++/FAQ*
其他資訊:comp.lang.c FAQ 每個月都會出現在該討論區中,
該檔案的維護者是 Steve Summit (scs@eskimo.com) 。
中文翻譯:用 "Big5" 內碼(在臺灣最廣為使用的 16 位元中文內碼)儲存
的中文譯文,可用 anonymous ftp 到以下地點取得:
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:運運算元多載(operator overloading)是做什麼的?
Q21:哪些運運算元可以/不能被多載?
Q22:怎樣做一個 "**"「次方」運運算元?
第7節:夥伴
------------
Q23:夥伴(friend)是什麼?
Q24:「夥伴」違反了封裝性嗎?
Q25:夥伴函式的優缺點?
Q26:「夥伴關係無繼承及遞移性」是什麼意思?
Q27:應該替類別宣告個成員函式,還是夥伴函式?
第8節:輸入/輸出:
---------------------------------------------
Q28:該怎樣替 "class Fred" 提供輸出功能?
Q29:為什麼我該用
Q30:為什麼我處理輸入時,會超過檔案的結尾?
Q31:為什麼我的程式執行完第一次迴圈後,會對輸入的要求不加理睬?
Q32:在 DOS 及 OS/2 的 binary 模式下,要怎樣來 "reopen" cin 及 cout?
========== POSTING #2 ==========
第9節:自由記憶體管理
----------------------
Q33:"delete p" 會刪去 "p" 指標,還是它指到的資料,"*p" ?
Q34:我能 "free()" 掉由 "new" 配置到的、"delete" 掉由 "malloc()" 配置到的
記憶體嗎?
Q35:為什麼該用 "new" 而不是老字號的 malloc() ?
Q36:為什麼 C++ 不替 "new" 及 "delete" 搭配個 "realloc()" ?
Q37:我該怎樣配置/釋放陣列?
Q38:萬一我忘了將 "[]" 用在 "delete" 由 "new Fred[n]" 配置到的陣列,會發生
什麼事?
Q39:成員函式做 "delete this" 的動作是合法的(並且是好的)嗎?
Q40:我該怎麼用 new 來配置多維陣列?
Q41:C++ 能不能做到在執行時期才指定陣列的長度?
Q42:怎樣確保某類別的物件都是用 "new" 建立的,而非區域或整體/靜態變數?
第10節:除錯與錯誤處理
------------------------
Q43:怎樣處理建構子的錯誤?
Q44:如果建構子會丟出例外的話,該怎麼處理它的資源?
第11節:Const 正確性
----------------------
Q45:什麼是 "const correctness"?
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) hides Base::f(float)" 是什麼意思?
⊙12B:繼承--一致性
Q60:我該遮蔽住由基底類別繼承來的公共成員函式嗎?
Q61:圓形 "Circle" 是一種橢圓 "Ellipse" 嗎?
Q62:對「圓形是/不是一種橢圓」這兩難問題,有沒有其他說法?
⊙12C:繼承--存取規則
Q63:為什麼衍生的類別無法存取基底的 "private" 東西?
Q64:"public:"、"private:"、"protected:" 的差別是?
Q65:當我改變了內部的東西,怎樣避免子類別被破壞?
⊙12D:繼承--建構子與解構子
Q66:若基底類別的建構子呼叫一個虛擬函式,為什麼衍生類別覆蓋掉的那個虛擬函
數卻不會被呼叫到?
Q67:衍生類別的解構子應該外顯地呼叫基底的解構子嗎?
⊙12E:繼承--Private 與 protected 繼承
Q68:該怎麼表達出「私有繼承」(private inheritance)?
Q69:「私有繼承」和「成份」(composition) 有多類似?
Q70:我比較該用哪一種:成份還是私有繼承?
Q71:我應該用指標轉型方法,把「私有」衍生類別轉成它的基底嗎?
Q72:保護繼承 (protected inheritance) 和私有繼承有何關連?
Q73:"private" 和 "protected" 的存取規則是什麼?
第13節:抽象化(abstraction)
-------------------------------
Q74:分離介面與實作是做什麼用的?
Q75:在 C++ 裡,我該怎樣分離介面與實作(像 Modula-2 那樣)?
Q76:ABC ("abstract base class") 是什麼?
Q77:「純虛擬」(pure virtual) 成員函式是什麼?
Q78:怎樣替整個類別階層提供列印的功能?
Q79:何時該把解構子弄成 virtual?
Q80:虛擬建構子 (virtual constructor) 是什麼?
========== 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:"inline virtual" 的成員函式真的會被 "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:怎樣把指向成員函式的指標傳給 signal handler、X event callback 等等?
Q113:當我想以成員函式做為中斷服務常式 (ISR) 時,為什麼產生(型態不
符)的錯誤?
Q114:為什麼我取不出 C++ 函式的位址?
Q115:怎樣宣告指向成員函式的指標陣列?
第19節:容器類別與 template
-----------------------------
Q116:怎樣自一個連結串列/雜湊表等等裡面,插入/存取/改變元素?
Q117:「樣版」(template)的用意是什麼?
Q118:"function template" 的語法/語意是什麼?
Q119:"class template" 的語法/語意是什麼?
Q120:什麼是「引數化型別」(parameterized 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 或是 ),或是其他
和 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 和 )。
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. (包含 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++. [g++ 的臭□列表 -- 請見 g++ 的檔案]
comp.lang.c
FAQ 1.10: 我搞糊塗了。NULL 保證一定是 0,但是 null 指標卻不是?
FAQ 2.3: 那麼,在 C 裡頭「指標和陣列等價」是什麼意思?
FAQ 4.2: [為什麼 "printf("%dn," 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) 或是 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++ 標準化方案在進行嗎?
有的;ANSI(美國的)和 ISO(國際的)組織正密切合作。ANSI-C++ 委員會稱為
"X3J16" ,而 ISO C++ 標準團體稱為 "WG21"。ANSI/ISO C++ 的標準過程中包含了
這些人:
AT&T, IBM, DEC, HP, Sun, MS, Borland, Zortech, Apple, O 等等等等。每次開
會約有 70 人,他們來自美、英、日、德、瑞典、丹麥、法國……(他們都有「區域
性」的委員會,派遣正式代表並主導「區域性」的會議)。
========================================
Q7:該到哪裡索取最新的 ANSI-C++ 標準草案?
ISO Committee Draft for C++ 以及 ANSI C++ Draft(將要供 public review 的文
件)可如此取得:
~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 s(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++經驗後,會發現這正是一種「資訊隱藏」的作法,是利
而非弊。好比說,程式員應該以切近該問題的方式來寫程式,而非以機器的語言來解
題。
========================================
Q16:行內函式是做什麼的?
行內函式(inline function)是個程式碼會塞入呼叫者所在之處的函式。就像巨集
一樣,行內函式免除了函式呼叫的額外負擔,以增進效率,並且(尤其是!)還能讓
編譯器對它施以最佳化(融合 "procedural integration")。不過和巨集不同
的是:它只會對所有引數求一次的值(在語意上,該“函式呼叫”和正常函式一樣,
只是比較罷了),以避免某些不易察覺的巨集錯誤。此外,它還會檢測引數的型
態,做必要的型別轉換(巨集對你有害;除非絕對必要,否則別再用它了)。
注意:過度使用行內函式會讓程式碼肥胖,於分頁(paging)環境下反而有負面的性
能影響。
宣告法:在函式定義處使用 "inline" 關鍵字:
inline void f(int i, char c) { /*...*/ }
或者是在類別內將定義包括進去:
class Fred {
public:
void f(int i, char c) { /*...*/ }
};
或是在類別外頭,以 "inline" 來定義該成員函式:
class Fred {
public:
void f(int i, char c);
};
inline void Fred::f(int i, char c) { /*...*/ }
=============================
■□ 第5節:建構子和解構子
=============================
Q17:建構子(constructor)是做什麼的?
建構子乃用來從零開始建立物件。
建構子就像個「初始化函式」;它把一堆散亂的位元組成一個活生生的物件。最低限
度它會初始化內部用到的欄位,也可能會配置所須的資源(記憶體、檔案、semaphore
、socket 等等)。
"ctor" 是建構子 constructor 最常見的縮寫。
========================================
Q18:怎樣才能讓建構子呼叫另一個同處一室的建構子?
沒有辦法。
原因是:如果你呼叫另一個建構子,編譯器會初始化一個暫時的區域性物件;但並沒
有初始化“這個”你想要的物件。你可以用預設引數(default parameter),將兩
個建構子合併起來,或是在私有的 "init()" 成員函式中共享它們的程式碼。
========================================
Q19:解構子(destructor)是做什麼的?
解構子乃物件之葬禮。
解構子是用來釋放該物件所配置到的資源,譬如:Lock 類別可能會鎖住一個
semaphore,解構子則用來釋放它。最常見的例子是:當建構子用了 "new" 以後,解
構子用 "delete"。
解構子是個「去死吧」的運作行為(method),通常縮寫為 "dtor"。
=========================
■□ 第6節:運運算元多載
=========================
Q20:運運算元多載(operator overloading)是做什麼的?
它可讓使用類別的人以直覺來操作之。
運運算元多載讓 C/C++ 的運運算元,能對自訂的型態(物件類別)賦予自訂的意義。它
們形同是函式呼叫的語法糖衣 (syntactic sugar):
class Fred {
public:
//...
};
#if 0
Fred add(Fred, Fred); //沒有運運算元多載
Fred mul(Fred, Fred);
#else
Fred operator+(Fred, Fred); //有運運算元多載
Fred operator*(Fred, Fred);
#endif
Fred f(Fred a, Fred b, Fred c)
{
#if 0
return add(add(mul(a,b), mul(b,c)), mul(c,a)); //沒有...
#else
return a*b + b*c + c*a; //有...
#endif
}
========================================
Q21:哪些運運算元可以/不能被多載?
大部份都可以被多載。
不能的 C 運運算元有 "." 和 "?:"(和以技術上來說,可算是運運算元的 "sizeof")。
C++ 增加了些自己的運運算元,其中除了 "::" 和 ".*". 之外都可以被多載。
底下是個足標(subscript)運運算元的例子(它會傳回一個參考)。最前面是“不用
”多載的:
class Array {
public:
#if 0
int& elem(unsigned i) { if (i>99) error(); return data[i]; }
#else
int& operator[] (unsigned i) { if (i>99) error(); return data[i]; }
#endif
private:
int data[100];
};
main()
{
Array a;
#if 0
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)"
這個函式(它的倍精確度版本在
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990889/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- APatch常見問題解答
- RapidWeaver 8常見問題解答API
- Ubuntu 常見問題和解答Ubuntu
- C語言常見使用問題2C語言
- C語言指標常見問題C語言指標
- [譯] HTTP/2 常見問題解答HTTP
- NSIS 之 NsDialogs 常見問題解答
- 【答疑】物件儲存OSS常見問題解答(工具類1)物件
- Rhinoceros 6 for Mac的常見問題解答ROSMac
- Screaming Frog SEO Spider常見問題解答IDE
- 小遊戲引擎常見問題解答遊戲引擎
- 關於CleanMyMac常見問題與解答Mac
- 【答疑】物件儲存OSS常見問題解答(諮詢類1)物件
- 犀牛Rhinoceros 6 for Mac的常見問題解答ROSMac
- Python程式設計常見問題與解答Python程式設計
- SOLIDWORKS認證考試常見問題解答Solid
- 業務規則的常見問題解答
- GNU GPL 許可證常見問題解答(三)
- 全志RV1108常見問題操作解答
- MongoDB常見問題解答:時間與時區MongoDB
- 域名解析常見問題盤點及解答
- SAP document builder一些常見問題的解答UI
- FAQ | PerfDog 常見問題解答第二期
- Apple M1晶片常見問題解答:您想要了解的這裡都有APP晶片
- 前端入門-day2(常見css問題及解答)前端CSS
- 【FAQ】統一掃碼服務常見問題及解答
- 【等保】二級等保常見問題解答彙總
- 【過等保】2022年過等保常見問題解答
- 光學字元識別工具包SmartZone常見問題解答字元
- 華為隨行WiFi 2暢享版常見問題解答WiFi
- 【答疑】物件儲存OSS常見問題解答(諮詢類2)物件
- 有關超聲波感測器的常見問題解答
- 程式碼簽名、驅動簽名的常見問題解答
- 域名解析需要多久生效?域名解析常見問題解答
- 【FAQ】申請Health Kit許可權的常見問題及解答
- 常見問題
- Mac有防火牆嗎?關於Mac防火牆常見的問題解答Mac防火牆
- 阿里雲centos7伺服器nginx配置及常見問題解答阿里CentOS伺服器Nginx
- IPv6轉換常見問題盤點