推 ykjiang:終於有人講到重點了 :) 203.70.76.250 08/12
※ 引述《tester.bbs@bbs.csie.ncu.edu.tw (try or test)》之銘言:
> 自認對 OO 精通的人應該要能回答 gsj 的質疑才是, 否則 OO 就如其音,
> 黑黑來, 黑黑去, 黑壓壓的一片.
我記得前輩的 ID
日前發了不少好文讓我獲益良多
這些問題,敝人來嘗試一下 :)
> 物件導向 或 OOP 不知是否有特別強調 "非循序式" ? 印象中至少不是被
> 列為是 parallel programming 或 concurrent high level language .
> 學 OO 的要怎麼回答 ?
OO 不曾強調非循序
這很顯而易見
因為 OO 是循序的
但 OO 的重點不是這個
而是在於語言提供的高階抽象介面
> 在 object 封裝的內部對 data , code 是可以雜亂交錯, 你中有我,
> 我中有你那樣的混在一起, 還是分堆但包在封袋裡 ? 顯然 gsj 指出
> 了 OO 讓人看不清楚無法理解的一面.
> 如果程式語言與電腦的實體是不對稱的, 那這個質疑是有道理的, 這
> 不能用 abstraction 一筆帶過, 否則會被懷疑 OOP 是有效率的嗎 ?
這個問題並不屬於 OO,
這這問題是關係於硬體/作業系統設計與 compiler 的實作,
但我還是嘗試回應一下實作面的問題,
如果有錯還請其他前輩指正。
OO 在介面上把 data/code 封裝起來,
你在抽象介面上來看, data/code 是合為一體,
但在 compiler 的實作上,兩者當然是分開放,
(不好意思我沒接觸過 X86 跟 Windows 以外的東西,僅講我知道的東西)
static data member 放在 data seg,
local data member 放在 stack seg,
member function 放在 code seg,
還有一個比較特別的 virtual table 是跟著每一個 virtual obj 的 instance 跑。
我在概念上也回答這個問題,
事實上,OO 的理念就是希望「讓你(選擇)可以不用知道內部實際作業」,
當然如果對內部怎麼實作有興趣的話,書跟期刊翻一翻就是。
事實上循序性的語言, sub-rutine 跟 function 不也是把部分細節隱藏嗎 :)
只不過 OO 是把資料跟程式封裝在一起。
我們可以很合理的了解,
有很多的程式碼只對特定的資料有意義,
那為什麼不封裝在一起?
當然也有的程式碼對很多資料都有意義,
那就沒有必要跟資料一起封裝,
我們改用 generic programming,(如STL)
至於 OO 跟 GP 有沒有違背?
當然沒有,你可以看需求來選擇用誰,
更棒的是,兩者都可以用上。
http://www.china-pub.com/computers/bookinfo/zfbs.htm#g
> 不然就是效率的稍微(這也得具體說明)犧牲, 可換來那些更值得的東東 ?
以效率來說,
一個好的 C++ compiler,
對於沒有 virtual function 的 class,
理當要達到與 C 相等的效能,
事實上,呼叫 member function 跟呼叫一般 function 的成本是一樣的,
這是顯而易見的,因為哪個 function 會被呼叫,是在 compile-time 就可以決定的,
但鑒於 C++ 較複雜以及發展沒有 C 久,
請給 compiler 設計者多一點時間 :)
Stroustrup 在設計 C++ 的時候,也考慮過效能問題,
他認為要求 compiler 作到只比 C 多出 5% 的 overhead 並不算過分。
至於 virtual function 的部份,
因為每個 virtual function 的 binding 要在執行期來決定,
這必須老實承認,講這個 overhead 很小那一定是騙人的,
我知道各家的 compiler 在這方面都有特別的最佳化處理,
但實際上效能的差異是多少我就沒有數據。
搜索引擎搜一下 "c/c++ performance" 有不少的實驗。
不過這個部份其實才是 OO 的菁華,
如果用 C 來實作一樣的機制,你一樣要承受這些 overhead。
這 JJH 有講過了 :)
「成本,就是成本,成本不是缺點,該付出的代價,就是要付。」
GTK 也是用 C 來實作 OO,我是沒聽過有人抱怨他效能太慢 O_O
> 譬如 Interactive 的 interpreter 相對於 compiler , 另外,
> 就是改善的趨勢會是甚麼 ? (譬如使用中間碼的 interpreter)
> 其次, 在那些地方或條件下, OOP 可以像一般的 C 使用 pointer
> 那樣方便的 reference structured data (如 array 或 record) ?
我看了這三天的討論,
所有的焦點都只在「封裝」上打轉,
完全沒有人提到 OO 的另外兩個靈魂:
「繼承」與「多型」。
若沒有繼承與多型,
封裝的好處就大大打了折扣,
繼承建立在封裝之上,
而程式碼複用是繼承最明顯的好處之一。
程式設計師的三大美德:「懶惰,急躁,跟自大」
同樣的東西最好不要再打一次,多打一次,就多一次錯誤的機會。
當然關於這件事,今年一月 gsj 也說過名言:
「在你開始研究什麼叫作 "繼承語法" 很久很久之前
你的阿公早就用 Copy + Paste 作好這件事了
包含你那偉大的 OO Compiler 內部都是這樣處理的!」
Master 告訴他:
「事實上雖然你沒說錯,
但既然這麼簡單的copy & paste事情為何不交給Compiler 代勞呢?
妳覺得人工作業慢慢地比較神氣嗎? 」
(Master 這篇文章差點讓我把口水噴到螢幕上,
因為我腦海裡浮現了 gsj 低頭努力 copy & paste 的畫面  ̄▽ ̄)
多型建立在繼承之上,
他讓你在程式碼的複用上有更靈活的變化,
base pointer 可以在執行期根據所指到的 derived object 的類別,
自動決定該呼叫的函數。
當然你用 C 配合一下執行期判別一樣可以做到同樣的功能,
只不過現在懶惰的程式設計師可以把這工作交給 compier 去做了。
道理還是一樣..
「懶惰,急燥,與自大。」
「人工慢慢的作業沒有比較神氣。」
--
To iterate is human, to recurse is divine.
遞迴只應天上有, 凡人該當用迴圈. L. Peter Deutsch
--
夫兵者不祥之器物或惡之故有道者不處君子居則貴左用兵則貴右兵者不祥之器非君子
之器不得已而用之恬淡為上勝而不美而美之者是樂殺人夫樂殺人者則不可得志於天下
矣吉事尚左凶事尚右偏將軍居左上將軍居右言以喪禮處之殺人之眾以哀悲泣之戰勝以
喪禮處之道常無名樸雖小天下莫能臣侯王若能守之萬物將自賓天地相合以降甘露民莫
之令而自均始制有名名亦既有夫亦將知止知止218-168-41-229.dynamic.hinet.net海