C++ 之父給初學者的信


C++ 之父給初學者的信
From: bs@alice.att.com (Bjarne Stroustrup)
Newsgroups: comp.os.msdos.programmer,
comp.sys.ibm.pc.programmer,
comp.lang.c++,comp.lang.c
Subject: Newbie Wants Advice on C-Programming
Summary: general comments on learning C++
Date: 29 Dec 92 17:52:53 GMT
Organization: AT&T Bell Laboratories, Murray Hill NJ
Lines: 288

There has - under various headings - been several related discussions about the proper way to learn C++, C++'s relation to C, C++'s relation to Smalltalk, the difference (or not) between data abstraction and object-oriented programming, etc.

雖然標題不同,不過跟 C++ 學習相關的討論也出現過很多次了,例如 C++ 與 C 的關聯,C++ 與 Smalltalk 的關係,資料抽象與物件導向程式設計的不同等。

I think the practical concern underlying many of these discussions is:
Given that I don't have much time to learn new techniques and concepts, how do I start using C++ effectively?

我覺得這些討論實際上的重點是:如果沒時間學新技巧或觀念的話,如何才能快速上手 C++?

It is clear that to use C++ ''best'' in an arbitrary situation you need a deep understanding of many concepts and techniques, but that can only be achieved through years of study and experiments. It is little help to tell a novice (a novice with C++, typically not a novice with programming in general), first to gain a thorough understanding of C, Smalltalk, CLOS, Pascal, ML, Eiffel, assembler, capability based systems, OODMBSs, program verification techniques, etc., and then apply the lessons learned to C++ on his or her next project. All of those topics are worthy of study and would - in the long run - help, but practical programmers (and students) cannot take years off from whatever they are doing for a comprehensive study of programming languages and techniques.

顯然地,想隨時隨地都善加利用 C++ 的話,得深入理解許多觀念與技巧,而這是多年學習與實作才有可能獲得。告訴初學者(C++ 初學者,一般來說,不會是程式語言的初學者):「要先有 C、Smalltalk、CLOS、Pascal、ML、Eiffel、組語、能力基礎系統、OODMBS、程式驗證技巧等,接著在下個專案中使用 C++ 中學到的東西」這種說法沒什麼用。這些主題都值得研究,而且確實也各有其應用場合,不過實務上,程式設計者(與學生)不可能丟下手邊的工作,只為了全面研究程式語言及技巧。

On the other hand, most novices understand that ''a little knowledge is a dangerous thing'' and would like some assurance that the little they can afford time to learn before/while starting their next project will be of help and not a distraction or a hinderance to the success of that project. They would also like to be confident that the little new they can absorb immediately can be part of a path that can lead to the more comprehensive understanding actually desired rather than an isolated skill leading nowhere further.

另外,多數初學者都知道「一知半解的危險性」,因此想要某種程度的確認,現在付出的這一丁點時間學到的東西,能在接下來的專案派上用場,或者至少別拖累,造成專案的困擾。他們也想要的是,吸收到的這些東西,對於最後真正想全面理解的東西,會是有益的,而不只是用來解決眼前問題的獨立性技巧。

Naturally, more than one approach can fulfill these criteria and exactly which to choose depends on the individual's background, immediate needs, and the time available. I think many educators, trainers, and posters to the net underestimate the imporatance of this: after all, it appears so much more cost effective - and easier - to ''educate'' people in large batches rather than bothering with individuals.

當然,是有些方法能符合這些考量,至於選用哪個方法,則依個人的背景、立即需求與可用的時間來決定。我想許多教育者、訓練師或以及海報都低估了這個重要性:畢竟,教一群人顯然比較有效益,也比較輕鬆。

Consider a few common questions:
I don't know C or C++, should I learn C first?
I want to do OOP, should I learn Smalltalk before C++?
Should I start using C++ as an OOPL or as a better C?
How long does it take to learn C++?

來看幾個常見的問題:
我不懂 C 或 C++,要不要先學 C?
我想寫物件導向程式,要不要先學 Smalltak 再學 C++?
要把 C++ 當物件導向語言用嗎?或者是更好的 C?
學 C++ 要花多久時間?

I don't claim to have the only answers ''the (only) right answers'' to these questions. As I said the ''right'' answer depends on the circumstances. Most C++ textbook writers, teachers, and programmers have their own answers. For example, I seem to remember that the C++ FAQ discusses these questions. My answers are based on years of programming in C++ and other languages, teaching short C++ design and programming courses (mainly to professional programmers), consulting about to introduction of and use of C++, discussing C++, and generally thinking about programming, design, and C++.

這些問題對我來說,都不會只有唯一的答案-(唯一)正確的答案。就我而言,「正確」答案都是視情況而定。多數 C++ 教科書的作者、教師、程式設計者也各有其答案。例如,我記得 C++ FAQ 好像也討論過這些問題。我的回答會是基於在 C++ 與其他語言有多年設計經驗、教過一小段 C++ 設計與程式設計課程(對象主要是專業的程式設計者)、作過 C++ 導入與使用的顧問、C++ 的討論、經常思考程式、設計與 C++ 等。

I don't know C or C++, should I learn C first?

我不懂 C 或 C++,要不要先學 C?

No. Learn C++ first. The C subset of C++ is easier to learn for C/C++ novices and easier to use than C itself. The reason is that C++ provides better guarantees than C (stronger type checking). In addition, C++ provides many minor features, such as the `new' operator, that are notationally more convenient and less error-prone than their C alternatives. Thus, if you plan to learn C and C++ (or just C++) you shouldn't take the detour through C. To use C well, you need to know tricks and techniques that aren't anywhere near as important or common in C++ as they are in C. Good C textbooks tends (reasonably enough) to emphasize the techniques that you will need for completing major projects in C. Good C++ textbooks, on the other hand, emphasizes techniques and features that lead to the use of C++ for data abstraction and object-oriented programming. Knowing the C++ constructs, their (lower-level) C alternatives are trivially learned (if necessary).

不!直接學 C++。C++ 的 C 子集對 C/C++ 初學者來說比較容易,比使用 C 本身還比較容易。原因在於,C++ 提供了比 C 更多的安全性(強型別檢查)。除此之外,C++ 還提供了許多小特性,像是 new 運算子,這明顯比 C 中對應的功能方便且更能避免錯誤。因此,如果想學 C 與 C++(或只要 C++),不用迂迴地從 C 開始學,C 要用得好,會需要知道一些技法與技巧,而這些在 C++ 中不像在 C 那麼重要與常見,好的 C 教科書會(適度地)強調完成一個大型 C 專案需要的技術,相對地,好的 C++ 教科書會強調的技巧與特性,在於運用 C++ 進行資料封裝、物件導向程式設計。瞭解了 C++ 的結構,它們在(低階)C 的對應部份自然也就學會了(如果有需要的話)。

To show my inclinations:
To learn C use:
Kernighan and Ritchie:
The C programming Language (2nd edition)
Prentice Hall, 1988.

我個人的偏好是:
要學 C 的話,用這一本書:
Kernighan and Ritchie:
The C programming Language (2nd edition)
Prentice Hall, 1988.

To learn C++ use:
Stroustrup:
The C++ programming Language (2nd edition)
Addison Wesley, 1991.

要學 C++ 的話用這本:
Stroustrup:
The C++ programming Language (2nd edition)
Addison Wesley, 1991.

Both books have the advantage of combining a tutorial presentation of language features and techniques with a complete reference manual. Both describes their respective languages rather than particular implementations and neither attempts to describe particular libraries shipped with particular implementations.

這兩本的優點是可作為程式語言教學與技術參考手冊,說明各自的語言而非特定實作,不會說明特定實作才有的特定程式庫。

There are many other good textbooks and many other styles of presentation, but these are my favorites for comprehension of concepts and styles. It is always wise to look carefully at at least two sources of information to compensate for bias and possible shortcommings.

是有許多其他不錯的教科書與呈現方式,不過就觀念與風格的互補性來看的話,這兩本是我的最愛。詳細地看過兩個以上的資訊來源總是明智的,在一些偏重或可能的缺點才能互補。

I want to do OOP, should I learn Smalltalk before C++?

我想寫物件導向程式,要不要先學 Smalltak 再學 C++?

No. If you plan to use C++, learn C++. Languages such as C++, Smalltalk, Simula, CLOS, Eiffel, etc., each has their own view of the key notions of abstraction and inheritance and each support them in slightly different ways to support different notions of design. Learning Smalltalk will certainly teach you valuable lessons, but it will not teach you how to write programs in C++. In fact, unless you have the time to learn and digest both the Smalltalk and the C++ concepts and techniques, using Smalltalk as a learning tool can lead to poor C++ designs.

不!如果想學 C++,就學 C++。像 C++、Smalltalk、 Simula、CLOS、Eiffel 等的程式語言,對於抽象、繼承等上,各有其觀點,而這些程式語言在不同特性的支援上會有一些差異,學習 Smalltalk 當然會得到不少寶貴的觀念,但是它不會告訴你怎麼用 C++ 寫程式,事實上,除非你有時間學習、消化 Smalltalk 與 C++ 兩者的觀念與技術,不然以 Smalltalk 作為學習工具,對 C++ 的設計沒有太大幫助。

Naturally, learning both C++ and Smalltalk so that you can draw from a wider field of experience and examples is the ideal, but people who haven't taken the time to digest all the new ideas often end up ''writing Smalltalk in C++'' that is applying Smalltalk design notions that doesn't fit well in C++. This can be as sub-optimal writing C or Fortran in C++.

當然,最理想的是 C++ 與 Smalltalk 都學,以便從更廣的領域中取得更多經驗與實證,不過在還沒有時間消化全部的新想法前,通常就會變成「在 C++ 中寫 Smalltalk」,也就是說將 Smalltalk 設計中一些不是很符合 C++ 特性部份拿來套用,這就像在 C++ 中寫 C 或是 Fortran 同樣地不理想。

One reason often quoted for learning Smalltalk is that it is ''pure'' and thus force people to think and program ''object oriented.'' I will not go into the discussion about ''purity'' beyond mentioning that I think that a general purpose programming language ought to and can support more than one programming style (''paradigm'').

學 Smalltalk 常見的理由是,它很「純」,並且能迫使人們以物件導向的方式思考與設計程式。在討論「純」之前,應該先談到的是,我認為通用型的程式語言,應該能支援一種以上的程式設計風格(模式)。

The point here is that styles that are appropriate and well supported in Smalltalk are not necessarily appropriate for C++. In particular, a slavish following of Smalltalk style in C++ leads to inefficient, ugly, and hard to maintain C++ programs. The reason is that good C++ requires design that takes advantage of C++'s static type system rather than fights it. Smalltalk support a dynamic type system (only) and that view translated into C++ leads to extensive unsafe and ugly casting.

這邊的重點在於,Smalltalk 中適當的風格,在 C++ 不一定適合,在 C++ 中毫無創意地遵從 Smalltalk 風格,會有效率不良,令 C++ 程式難以維護的問題,原因在於好的 C++ 要利用到 C++ 靜態型別系統的設計,而不是抗拒它。Smalltalk(只)支援動態型別系統,而這些觀點轉移至 C++ 將發生廣泛的安全性與醜陋的型態轉換問題。

I consider most casts in C++ programs signs of poor design. Some casts are essential, but most aren't. In my experience, old-time C programmers using C++ and C++ programmers introduced to OOP through Smalltalk are among the heaviest users of casts of the kind that could have been avoided by more careful design.

我認為 C++ 程式中多數的型態轉換都是不良設計的表現,有一些轉型是必要的,但大部份並非如此,就我的經驗得知,一些過去使用 C 的 C++ 程式設計者,以及從 Smalltalk 進入 OOP 世界的人,都是這類型態轉換的使用者,而他們可以更細心地設計以避免(這些不良設計)。

In addition, Smalltalk encourages people to see inheritance as the sole or at least primary way of organizing programs and to organize classes into single-rooted hierarchies. In C++, classes are types and inheritance is by no means the only means of organizing programs. In particular, templates is the primary means for representing container classes.

除此之外, Smalltalk 鼓勵人們視繼承為組織程式的靈魂,或至少是主要方法,將類別組織為單根的體系。在 C++ 中,類別是型態,而繼承無論如何都不會是組織程式的唯一方法,尤其是,模版會用來表現容器類別。

I am also deeply suspicious of arguments proclaiming the need to FORCE people to write in an object-oriented style. People who don't want to learn can, on average, not be taught with reasonable effort and there is in my experience no shortage of people who DO want to learn. Unless you manage to demonstrate the principle behind data abstraction and object-oriented programming all you'll get is inappropriate ''barouque'' misuses of the language features that support these notions - in C++, Smalltalk, or whatever.

我也很懷疑那些宣稱必須以物件導向風格撰寫程式的論調。平心而論,對於拒絕學習的人,沒辦法教他們得付出努力,而就我的經驗來說,這種不想學習的人不少。除非你想強調資料抽象化與物件導向程式設計背後的原則,否則 C++、Smalltalk,或其他支援這些概念的語言特性,最後只會是「巴洛克式」的誤用。

See ''The C++ Programming (2nd Edition)'' and in particular Chapter 12 for a more thorough discussion of the relation between C++ language features and design.

看看《The C++ Programming (2nd Edition)》,尤其是第 12 章關於 C++ 特性及設計的討論。

Should I start using C++ as an OOPL or as a better C?

要把 C++ 當物件導向語言用嗎?或者是更好的 C?

That depends. Why do you want to start using C++? The answer to that question ought to determine the way you approach C++; not some one-size-fits-all philosophy. In my experience the safest bet is to learn C++ ''bottom up,'' that is first learn the features C++ provides for traditional procedural programming, the ''better C'' sub-set, then learn to use and appreciate the data abstraction features, and then learn to use class hierarchies to organize sets of related classes.

這得視情況而定,為什麼你要用 C++ 呢?這問題的答案決定了你怎麼用 C++,不過不是一體適用的的哲學。就我的經驗來說,最安全的押注方式是「自底而上」學習 C++,也就是說先學 C++ 在傳統程序設計上提供的特性 - 「更好的 C 子集」,然後學著使用與理解資料抽象化的特性,並且學著使用類別體系來組織相關的類別集合。

It is - in my opinion - dangerous to rush through the earlier stages because there is too high a probability of missing some key point.

以我的觀點來說,匆忙略過初階部份很危險,因為很可能跳過了關鍵的部份。

For example, an experience C programmer might consider the ''better C'' subset of C ''well known'' and skip the 100 pages or so of a textbook that describes it. However, in doing so he might miss the ability to overload functions, the difference between initialization and assignment, the use of the `new' operator for allocation, the explanation of references, or some other minor feature in such a way that it will come back to haunt him at a later stage where sufficient new concepts are in play to complicate matters. If the concepts used in the better C subset are known the 100 pages will only take a couple of hours to learn and some details will be interesting and useful. If not, the time spent is essential.

例如,有經驗的 C程式設計者可能自認為熟悉 C,誤以為熟知 C++ 中「更好的 C 子集」,就跳過了書本中描述這部份的 100 多頁,然而這麼作,可能會忽略函式重載的能力、配置時 new 運算子的使用、參考的說明、或一些其他小特性,以至於後續還必須回想這些複雜的東西是在哪出現的。如果已經知道更好 C 子集的觀念,學習這 100 多頁只會花幾個小時,有些細節是有趣且有用的,即使不是這樣,也是得付出這些時間。

Some people have expressed fear that this ''gradual approach'' leads people to write in C style forever. This is of course a possible outcome, but nowhere as likely as proponents of ''pure'' languages and proponents of the use of ''force'' in teaching programming like to believe. The key thing to realize is that using C++ well as a data abstraction and/or object-oriented language requires the understanding of a few new concepts that have no direct counterpart in languages such as C and Pascal.

有些人表示,他們怕這種「漸進方式」會使得人們使用 C 風格來寫程式,這確實是有可能,不過這會是程式教學上「純」語言支持者與發揮「能力」支持者的信仰問題,關鍵在於必須瞭解,要在資料抽象化與(或)物件導向程式語言上善加利用 C++,必須要認識一些新觀念,而這些新觀念與一些語言,例如 C 與 Pascal 之類的語言沒有直接關聯。

C++ isn't just a new syntax for expressing the same old ideas - at least not for most programmers. This implies a need for education, rather than mere training. New concepts have to be learned and mastered through practice. Old and well-tried habits of work have to be re-evaluated, and rather than dashing of doing things ''the good old way'' new ways have to be considered - and often doing things a new way will be harder and more time-consuming than the old way - when tried for the first time.

C++ 不只是一些用來表現老舊想法的新語法,至少對多數程式設計者來說不是,在教授上也需如此,不能只是單純的訓練。必須學習新觀念並透過練習來掌握,在工作上既有的良好習慣必須要再度提煉,不能只是「既有的良好方法」之延伸,必須考慮新方法,在首次嘗試時,用新方法是會有點難,也往往會比用舊方法來得費時。

The overwhelming experience is that taking the time and making the effort to learn the key data abstraction and object-oriented techniques is worth while for almost all programmers and yields benefits not just in the very long run but also on a three to twelve month timescale. There are benefits in using C++ without making this effort, but most benefits requires the extra effort to learn new concepts - I would wonder why anyone not willing to make that effort would switch to C++.

經驗幾乎都是如此,付出時間與努力學得的關鍵資料抽象化與物件導向技巧,對大多數程式設計者絕對值得,而產生的效益最終還能持續三到十二個月的時間。使用 C++ 時是有些不費力就可得到的好處,但大多數的好處,得付出額外心力學習新觀念才能獲得。我覺得奇怪的是,為什麼有人覺得可以不費力地轉換至 C++。

When approaching C++ for the first time, or for the first time after some time, take the time to read a good textbook or a few well chosen articles (the C++ Report and the C++ Journal contain many). Maybe also have a look at the definition or the source code of some major library and consider the techniques and concepts used. This is also a good idea for people who has used C++ for some time. Many could do with a review of the concepts and techniques. Much has happened to C++ and its associated programming and design techniques since C++ first appeared. A quick comparison of the 1st and the 2nd edition of ''The C++ Programming Language'' should convince anyone of that.

第一次接觸 C++,或是一段時間之後又再度接觸 C++ 時,請花點時間看本好書或是精選文章(C++ Report 與 C++ Journal Contain 有很多),也許看些主函式庫的定義與原始碼,並思考當中使用的技巧與觀念,這對用過 C++ 的人來說也是個不錯的主意,可以複習對觀念與技巧,在 C++ 首次問市之後,期間 C++ 又發生了不少事,而相關的程式編寫與設計技巧也有所改變,比較一下《The C++ Programming Language》第 1 版與第 2 版的差異,任何人都會相信這點。

How long does it take to learn C++?

學 C++ 要花多久時間?

Again, that depends. It depends both on your experience and on what you mean by ''learning C++.'' The syntax and basics for writing C++ in the better C style plus defining and using a few simple classes takes a week or two for a programmer. That's the easy part. The main difficulty, and the main fun and gain comes from mastering new design and programming techniques. Most experienced programmers I have talked with quotes times from a half year to one and a half year for becomming really comfortable with C++ and the key data abstraction and object-oriented techniques it supports. That assumes that they learn on the job and stay productive - usually by programming in a ''less adventurous'' style of C++ during that period. If one could devote full time to learning C++ one would be comfortable faster, but without actual application of the new ideas on real projects that degree of comfort could be misleading. Object-oriented programming and object-oriented design are essentially practical - rather then theoretical - disciplines. Unapplied, or applied only to toy examples, these ideas can become dangerous ''religions.''

同樣地,視情況而定,這依經驗以及所謂「學 C++」是什麼而定,以更好的 C 風格而言,必要的語法及基礎,加上定義與使用一些簡單類別來寫 C++,對程式設計者來說得花上一到兩星期的時間,這還只是簡單的部份,主要的困難、樂趣及收獲,來自於新設計與程式編寫技巧,我遇過的有經驗程式設計者,多半花了半年至一年半的時間,才能真正熟悉 C++ 與其支援的關鍵資料抽象化與物件導向技巧。這是他們仍在職且持續保有生產力的假設前題下 - 這段時間通常以「較不冒險」的 C++ 風格撰寫程式。如果有人能全心付出時間來學 C++,是能更快熟悉,不過無法在實際專案上使用新想法會令人不安。以物件導向撰寫程式以及物件導向設計基本上是實務(而不是理論)法則,無法應用或者只應用在一些玩具般的案例,這些想法可能變 成危險的「教條」。

Note that learning C++ is then primarily leaning programming and design techniques, not language details. Having worked through a good textbook I would suggest a book on design such as Grady Booch:
Object Oriented Design with examples
Benjamin Cummings 1990.

注意,學 C++ 主要是在學習程式編寫與設計技巧,而不是語言細節,在看過一本好書後,設計上我再建議 Grady Booch 這本:
Object Oriented Design with examples
Benjamin Cummings 1990.

which has the nice property of having longish examples in five different languages (Ada, CLOS, C++, Smalltalk, and Object Pascal) and is therefore somewhat immune to the language biogotry that mar some design discussions. The parts of the book I like best is the presentation the design concepts and the example chapters.

這本不錯的地方是,使用了五種不同的程式語言(Ada、CLOS、C++、Smalltalk 與 Object Pascal)撰寫了的略長範例,因而可避免因語言差異而損失了一些設計討論,這本書我最喜歡的部份,是設計觀念的表現方式與範例章節。

Looking at design contrasts sharply with the approach of looking very carefully at the details of the definition of C++ - usually using the ARM:
Ellist&Stroustrup
The Annotated C++ Reference Manual
Addison-Wesley, 1990

重視 C++ 定義在設計上要如何實現的話 - 通常可以看 ARM:
Ellist&Stroustrup
The Annotated C++ Reference Manual
Addison-Wesley, 1990

which is a book containing much useful information, but no information about how to write C++ programs. A focus on details can be very distracting and lead to poor use of the language. You wouldn't try to learn a foreign language from a dictionary and grammar, would you?

這本書是有很多內容,不過沒有談到怎麼寫 C++。對細節的著重令人注意力不集中,而且很少談到語言的運用。要學習一門外國語,應該不會想從字典及文法書開始吧?你會嗎?

When learning C++, it is essential to keep the key design notions in mind so that one doesn't get lost in the language technical details. That done, learning and using C++ can be both fun and productive. A little C++ can lead to significant benefits compared to C, further efforts to understand data abstraction and object-oriented techniques yields further benefits.

在學 C++ 時,基本上要記得關鍵的設計概念,才不會迷失在語言的技術細節之中,這麼作的話,C++ 的學習與運用才會有趣而具有生產力,只要一點點的 C++,就能比使用 C 得到更多好處,進一步地認識資料抽象化與物件導向技巧,則能獲得更多的效益。

  • Bjarne Stroustrup