• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            OxFAN

            ::Just For Fun::

               :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              3 Posts :: 1 Stories :: 1 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(4)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            2009年4月30日 #

            [轉(zhuǎn)自TopLanguages里的 一篇帖子,并非原譯文,《常見邏輯謬誤》譯文地址:http://www.yeeyan.com/articles/view/65452/28581]

            當(dāng)你與別人討論,嘗試獲得答案或解釋時,你可能會遇到一些人犯上邏輯謬誤。這樣的討論是無意義的。你可能嘗試向?qū)κ忠笞C據(jù)或提供其他假設(shè),令你獲得更好或更簡 單的解釋。如果都失敗,可以嘗試指出你討論對手的問題。你可辨認他的邏輯問題以免深究,以及可告知討論對手關(guān)於他的謬誤。以下是簡單介紹其中最常見的謬誤: 

            人身攻擊(ad hominem): 
            拉丁語「向著人」的意思。辯者用人身攻擊來攻擊對手,而不是在討論議題。當(dāng)辯者不能用證據(jù)、事實或理由去維護他的立場,他可能透過標(biāo)簽、稻草人、罵人、挑釁及憤 怒的人身攻擊方式來攻擊對手。 

            訴諸無知(appeal to ignorance / argumentum ex silentio): 
            以訴諸無知作為某些證據(jù)。(例如:我們沒有證據(jù)說神不存在,所以祂一定存在。又例如:由於我們沒有關(guān)於外星人的知識,這表示他們并不存在。)對某些東西的無知, 是與它的存在與否無關(guān)。 

            全知論據(jù)(argument from omniscience): 
            (例如:所有人都相信某些東西,每個人都知道的。) 
            辯者需要有全知能力以清楚每個人的信仰、懷疑或他們的知識。小心如「所有」、「每個人」、「每種東西」、「絕對」等詞語。 

            訴諸信心(appeal to faith): 
            (例如:如果你不相信,是不能清楚明白的。)如果辯者倚仗信心作為他論據(jù)的根基,那麼你在以後的討論所能得到的將不多。根據(jù)定義,「信心」是倚靠相信,并非靠邏 輯或證據(jù)支持。信心倚賴非理性的思想,并會產(chǎn)生不妥協(xié)。 

            訴諸傳統(tǒng)(appeal to tradition): 
            (類似主流思想謬誤)(例如:占星、宗教、奴隸)只因為人們以此為傳統(tǒng),與它本身的存活能力無關(guān)。 

            訴諸權(quán)威(argument from authority / argumentum ad verecundiam): 
            以「專家」或權(quán)威的說話作論據(jù)的根基,而不是用邏輯或證據(jù)來支持該論據(jù)。(例如:某某教授相信創(chuàng)造科學(xué)。)只由於某個權(quán)威的聲稱,不足以代表他已令這聲稱正確。 假如辯者展示某專家的論據(jù),那麼看看它有否伴隨著原因,以及它背後證據(jù)的來源。 

            不良後果論據(jù)(argument from adverse consequences): 
            (例如:我們應(yīng)判被告有罪,否則其他人會仿效而犯上類似的罪行。)只因為討厭的罪行或行為出現(xiàn),并不足以代表被告犯了該罪,或代表我們應(yīng)判他有罪。(又例如:災(zāi) 難的出現(xiàn)是因為神懲罰不信者,所以我們都應(yīng)該信神。)只因災(zāi)害或慘劇發(fā)生,與神是否存在、或我們該信甚麼并無關(guān)系。 

            恐嚇論據(jù)(argumentum ad baculum): 
            論據(jù)根基於恐懼或威脅。(例如:如果你不信神,你將會下地獄被火燒。) 

            無知論據(jù)(argumentum ad ignorantiam): 
            誤導(dǎo)性的論據(jù),倚仗於人們的無知。 

            群眾論據(jù)(argumentum ad populum): 
            論據(jù)訴諸感性的弱點,而非事實和原因,旨在煽動群眾的支持。 

            主流思想謬誤(bandwagon fallacy): 
            只因為很多人相信或?qū)嵺`,便認為一個思想有價值。(例如:大多數(shù)人相信神,所以它一定是真的。)只因為很多人相信某些東西,與那是事實與否并無關(guān)系。如很多人在 黑死病時期都相信疫癥是由於魔鬼引起,有多少人相信跟疫癥的起因全無關(guān)系。 

            竊取論點(begging the question): 
            (例如:我們必須鼓勵年青人去崇拜神,以灌輸?shù)赖滦袨椤#┛墒亲诮膛c崇拜真的產(chǎn)生道德行為嗎? 

            循環(huán)論證(circular reasoning): 
            陳述某命題,而其實那正是需要被證實的。(例如:神存在是因為圣經(jīng)有記載,圣經(jīng)存在是因為神所默示的。) 

            構(gòu)成謬誤(composition fallacy): 
            當(dāng)某論據(jù)的結(jié)論,是倚靠由某東西從部份至整體、或從整體至部份的錯誤特性。(例如:人類有意識,而人體和人腦都是由原子組成,所以原子都有意識。又例如:文書處 理軟件由佷多原位組(byte)組成,所以一個原位組是組成文書處理軟件的一部份。) 

            確認性偏見(confirmation bias): 
            (類似監(jiān)視下的選擇)這是指一種選擇性的思想,集中於支持相信的人已相信的證據(jù),而忽略反駁他們信念的證據(jù)。確認性偏見常見於人們以信心、傳統(tǒng)及成見為根據(jù)的信 念。例如,如果有些人相信祈禱的力量,相信的人只會注意到少量「有回應(yīng)」的祈禱,而忽略大多數(shù)無回應(yīng)的祈禱。(這表示祈禱的價值最差只是隨機,最好也只有心理上 的安慰作用。) 

            混淆相關(guān)及起因(confusion of correlation and causation): 
            (例如:玩象棋的人男性比女性多,所以男性棋藝也比女性高。又例如:兒童觀看電視的暴力場面,成長後會有暴力傾向。)但是,那是由於電視節(jié)目引致暴力,還是有暴 力傾向的兒童喜歡觀看暴力節(jié)目?真正引致暴力的原因可能是完全與電視無關(guān)。Stephen 
            Jay Gould 把相關(guān)引致的無效假設(shè)稱為「可能是人類推理上兩三種最嚴重和最普遍的錯誤」。 

            錯誤二分法/排中(excluded middle / false dichotomy): 
            只考慮極端。很多人用亞理士多德式(Aristotelian)的「非此即彼」的邏輯去解釋上下、黑白、對錯、愛惡等。(例如:你若非喜歡它,就是不喜歡它。他 如不是有罪,就是無罪。)很多時人們沒有看到在兩個極端之間出現(xiàn)的連續(xù),這個宇宙也包含很多「可能」的。 

            隱藏證據(jù)(half truths / suppressed evidence): 
            故意欺騙的陳述,通常隱藏一些事實,而那是構(gòu)成準(zhǔn)確描述所必需的。 

            暗示/誘導(dǎo)性問題(loaded questions): 
            問題加入假設(shè),一旦回答便顯示了一個暗示性的同意。(例如:你停止了打你的妻子嗎?) 

            無意義的問題(meaningless question): 
            (例如「上面有多高?」「一切皆可能嗎?」)「上面」描述方向,不是可衡量的單位。假如一切都證實可能,那麼「不可能」都可能出現(xiàn),矛盾便出現(xiàn)。盡管一切不一定 證實可能,亦可以有無數(shù)的可能和無數(shù)的不可能。很多無意思的問題都包含了空廢的詞語,如 
            "is," "are," "were," "was," "am," "be," 或 "been." 

            統(tǒng)計性質(zhì)的誤解(misunderstanding the nature of statistics): 
            (例如:大多數(shù)美國人都死在醫(yī)院內(nèi),所以應(yīng)盡量遠離醫(yī)院。)「統(tǒng)計顯示,通常染上進食習(xí)慣的人,很少能生存。」-- Wallace Irwin 

            不當(dāng)結(jié)論(non sequitur): 
            拉丁語「它沒有跟隨」的意思。推斷或結(jié)論沒有跟隨已建立的前提或證據(jù)。(例如:在月圓時出生的人較多。結(jié)論:月圓引致出生率上升。)可是,是月圓引致較多出生, 還是由於其他原因(可能是統(tǒng)計上的期望差異)? 

            監(jiān)視下的選擇(observational selection): 
            (類似確認性偏見)指出有利的,卻忽略不利的事實。誰去過拉斯維加斯(Las 
            Vegas)賭場會見到人們在賭桌上和老虎機上贏錢,賭場經(jīng)理會響鐘及鳴笛以公告勝利者,卻永不會提及失敗者。這可令人覺得勝出的機會看來頗大,但是事實卻剛剛 相反。 

            錯誤因果(post hoc, ergo propter hoc): 
            拉丁語「它發(fā)生在之後,所以它是結(jié)果。」與不當(dāng)結(jié)論類似,不過與時間有關(guān)。(例如:她去了中國之後病了,所以中國有些東西令到她病。)可能她的病是由於其他原因 ,與中國完全無關(guān)。 

            證明不存在(proving non-existence): 
            當(dāng)辯者無法為他的聲稱提供證據(jù),他可能會挑戰(zhàn)他的對手,叫對手證明他的聲稱不存在。(例如:證明神不存在;證明不明飛行物體未曾到過地球;等等)盡管有人可以在 特定的限制中證明不存在,如在盒中沒有某些東西,可是卻無法證明普遍性、絕對性或認知性的不存在。無人能證明一些不存在的東西。提出聲稱的人必需自己證明那聲稱 的存在。 

            扯開話題(red herring): 
            辯者改變話題,以分散注意力。 

            實體化謬誤(reification fallacy): 
            當(dāng)人們把抽象的信念或假設(shè)性的構(gòu)想,當(dāng)作是實在的事物。如以IQ題作為真實衡量智慧的方法;由抽象的社會構(gòu)想而來的種族概念(盡管基因?qū)傩缘拇嬖冢醋越?jīng)揀選 的屬性組合,或者標(biāo)簽?zāi)骋唤M人;占星;耶穌;圣誕老人;等等。 

            滑坡謬誤(slippery slope): 
            一個步驟、法律、或行動的改變,可引致不良的後果。(例如:如果我們?nèi)菰S醫(yī)生幫助安樂死,那麼去到最後,政府會控制我們?nèi)绾嗡馈#┎灰欢ㄖ灰驗槲覀兊母淖儯霈F(xiàn) 了滑坡,便會使預(yù)計的後果實現(xiàn)。 

            片面辯護(special pleading): 
            以新鮮或特別的聲稱,抗衡對手的陳述;展示論據(jù)時只著重主題中有利或單一的范疇。(例如:神為何在世上創(chuàng)造這麼多苦難?答案是:你必須明白,神自有祂神奇的安排 ,我們沒有特權(quán)去知道的。又例如:星座是準(zhǔn)確的,但你必須先了解背後的理論。) 

            小眾統(tǒng)計(statistics of small numbers): 
            類似監(jiān)視下的選擇。(例如:我的父母吸了一世煙,但他們從未患過癌癥。又例如:我不管其他人如何講 Toyota,我的 Toyota 
            卻從未發(fā)生過問題。)只指出少量有利數(shù)據(jù),與整體機會并無關(guān)系。〔譯注:把 Yugo 改成 Toyota 使更易明白〕 

            稻草人謬誤(straw man): 
            創(chuàng)造一個虛假的情況,然後去攻擊它。(例如:進化論者認為所有事物都是隨機的。)大部份進化論者認為,在自然選擇的解釋下,可能包括偶發(fā)的成份,但并非全然依靠 隨機。抹黑你的對手只會令討論的功能偏離。 

            你我皆錯(two wrongs make a right): 
            指控其他人跟我們所做的同樣事情,為我們所作所為辯護。(例如:你有甚麼資格批評我?你也跟我做著一模一樣的事情!)控方的所犯的罪與討論本身并無關(guān)連。 

            分散注意力的謬誤(Fallacies of Distraction) 

                 * 兩難推理(False Dilemma) 
            錯謬:為多於一個答案的問題提供不足(通常兩個)的選擇,即是隱藏了一些選擇,最典型的表現(xiàn)是非黑即白觀點。 
                 * 例子:薩達姆是邪惡的,所以美軍是正義之師。 
                 * 解釋:除正邪之爭外,還有邪邪之爭及許多難分正邪的紛爭,所以不能單以薩達姆邪惡便認定美軍正義。 

                 * 訴諸無知(From Ignorance) 錯謬:因為不能否定,所以必然肯定,反之亦然。 
                 * 例子:沒有人能證明鬼不存在,那麼鬼肯定存在。 
                 * 解釋:總有些事是既不能否定,亦不能肯定的。除了肯定和否定,我們還可以存疑吧! 

                 * 滑坡謬誤(Slippery Slope) 錯謬:不合理使用連串因果關(guān)系。 
                 * 
            例子:遲到的學(xué)生要判死刑。因為遲到是不用功的表現(xiàn);將來工作也不勤力;不勤力導(dǎo)致公司損失;公司損失就會倒閉;公司倒閉會使人失業(yè);失業(yè)造成家庭問題;家庭問 題導(dǎo)致自殺率上升,為了防止自殺率上升,我們應(yīng)判遲到的學(xué)生死刑。 
                 * 
            解釋:滑坡謬誤中假定了連串「可能性」為「必然性」。比方說,遲到是否「必然」是不用功的表現(xiàn)?將來工作又是否「必然」不勤力?答案可想而知。例子雖然夸張,但 其實許多時候大家亦會犯相同錯誤而不自知。 

                 * 復(fù)合問題(Complex Question) 錯謬:一條問題內(nèi)包含兩個無關(guān)的重點。 
                 * 例子:你還有沒有干那非法勾當(dāng)?(你有干非法勾當(dāng)嗎?是否還有繼續(xù)?) 
                 * 解釋:簡單的一句提問,其實隱藏了兩個問題。你給予其中一條問題的答案,并不一定和另外一條的一樣。例如你有干非法勾當(dāng),但未必等於你還有繼續(xù)。 

            訴諸其他支持(Appeals to Motives in Place of Support) 

                 * 訴諸勢力(Appeal to Force) 錯謬:以勢力服人。 
                 * 例子:若你不想被解雇,你必須認同公司的制度。 
                 * 解釋:這是以工作機會強迫員工認同制度,員工不是依據(jù)制度好壞來決定認同與否。 

                 * 訴諸憐憫(Appeal to Pity) 錯謬:以別人的同情心服人。 
                 * 例子:希望你接受我這個多月來天天通宵撰寫的建議書。 
                 * 解釋:建議書的好壞,不在乎花了多少時間,而是取決於其內(nèi)容,提出「多月來天天通宵撰寫」只為搏取同情。 

                 * 訴諸結(jié)果(Consequences) 錯謬:以討好或不討好的結(jié)果服人。 
                 * 例子:你若不聽我的話,我便打你,不準(zhǔn)你外出,扣起你的零用。 

                 * 訴諸不中肯字詞(Prejudicial Language) 錯謬:以不中肯的字詞修飾論點。 
                 * 例子:凡是愛國的人都會認同訂立國家安全法的必要。 

                 * 訴諸大眾(Popularity) 錯謬:以被廣泛接納為理由服人。 
                 * 例子:看!人人都這樣說,還會錯嗎? 

                 * 一廂情愿(Wishful Thinking) 錯謬:以自己單方面想法作為論證根據(jù)。 
                 * 例子:因為我希望明天在戶外打球,所以明天一定天晴。 

            改變話題(Changing the Subject) 

                 * 人身攻擊(Attacking the Person) 錯謬〔一〕:以攻擊發(fā)言人代替攻擊其論點(因人廢言)。 
                 * 例子    :張廠長反對陳主任增加成本會計部的建議:「你當(dāng)然說成本會計十分重要,因為你是會計主任。」 
                 * 錯謬〔二〕:由回應(yīng)論點改變?yōu)楣粽擖c發(fā)起人的處境。 
                 * 例子    :你竟相信那些草根階層的說話? 
                 * 錯謬〔三〕:提出「你也是!」的不恰當(dāng)反問作論據(jù)。 
                 * 例子    :父:吸煙對健康不好!兒:為什麼你也吸? 

                 * 訴諸權(quán)威(Appeal to Authority) 錯謬〔一〕:訴諸討論的范疇以外的權(quán)威人士。 
                 * 例子    :經(jīng)濟學(xué)家都認為愛因斯坦的相對論是不可能的。 
                 * 錯謬〔二〕:訴諸權(quán)威人士的個人意見。 
                 * 例子    :羅局長說:「學(xué)生是政府的政策下最大得益者,所以學(xué)生無權(quán)批評領(lǐng)導(dǎo)人」 
                 * 解釋    :學(xué)生是政府的政策下最大得益者只是羅局長的說話,事實上學(xué)生是否政府的政策下最大得益者,卻沒有一個客觀答案。 
                 * 錯謬〔三〕:該范疇的權(quán)威人士不是認真的回應(yīng)。(例如:只是在開玩笑/喝醉。) 
                 * 例子    :「有香車自然有美人,BENZ的總公司董事長都這樣說啦!」 

                 * 匿名權(quán)威(Anonymous Authority) 錯謬:匿名的權(quán)威人士使人不能確定其權(quán)威性。 
                 * 例子:有位心理學(xué)家曾經(jīng)說過,每人都有犯罪傾向。 

                 * 作風(fēng)蓋過本體(Style Over Substance) 錯謬:討論者以作風(fēng)蓋過事件本身使人認為其論點正確。 
                 * 例子:以他一向的對人的態(tài)度,他一定不會對你好的。 

            歸納的謬誤(Inductive Fallacies) 

                 * 輕率的歸納(Hasty Generalization) 錯謬:用作歸納總體的樣本太少。 
                 * 例子:我問了十個人,有九個說反對民主黨。結(jié)論:原來九成香港人反對民主黨。 
                 * 解釋:單憑十個人論斷香港七百萬人?未免太輕率吧。若說訪問了數(shù)萬人,得出來的結(jié)果便較有說服力。 

                 * 不具代表性的例子(Unrepresentative Sample) 錯謬:用作歸納的例子不能代表其總體。 
                 * 例子:葉繼歡持械行劫;林過云奸殺多女;歐陽炳強紙盒藏屍。香港人肯定有殺人傾向。 

                 * 不當(dāng)類比(Weak Analogy) 錯謬:以兩件不相似的事件/事物作類比。 
                 * 例子:他對朋友這麼好,對女朋友一定很好呢。 

                 * 懶散的歸納(Slothful Induction) 錯謬:否定歸納得出來的恰當(dāng)結(jié)論。 
                 * 例子:即使有萬多個實驗證明化學(xué)物質(zhì)影響我們的感覺,我就是不相信。 

                 * 排除證據(jù)謬誤(Fallacy of Exclusion) 錯謬:故意把重要的證據(jù)隱藏,以得出不同的結(jié)論。 
                 * 例子: 

            統(tǒng)計三段論的謬誤(Fallacies Involving Statistical Syllogisms) 

                 * 例外(Accident) 錯謬:以概括情況加諸應(yīng)有的例外情況。 
                 * 例子:政府法例規(guī)定,行走此公路的汽車最高時速為七十公里。所以即使載著快要生產(chǎn)的產(chǎn)婦,亦不可開得快過七十公里。 

                 * 相反的例外(Converse Accident) 錯謬:以例外情況加諸應(yīng)有的概括情況。 
                 * 例子:我們準(zhǔn)許瀕死的病人注射海洛英,基於人人平等,也應(yīng)讓其他人注射海洛英。 

            因果的謬誤(Causal Fallacies) 

                 * 巧合謬誤(Coincidental Correlation) 錯謬:以個別情況肯定某種因果關(guān)系。 
                 * 例子:希希吃了一種藥,出現(xiàn)過敏反應(yīng)。因此,希希認為這種藥必然導(dǎo)致過敏反應(yīng)。 
                 * 解釋:希希遇到的只是個別例子,不能因此論斷該藥必然導(dǎo)致過敏反應(yīng)。 

                 * 復(fù)合結(jié)果(Joint Effect) 錯謬:當(dāng)兩件事都為某原因的結(jié)果時,以一事為另一事的原因。 
                 * 例子:記者報導(dǎo)離鄉(xiāng)背井的戰(zhàn)爭難民中的一家人:「他們因為房子被炮火所毀而逃到這里。」 
                 * 解釋:炮火導(dǎo)致這家人的房子被毀及離鄉(xiāng)逃難;房子被毀并不導(dǎo)致這家人離開原居地。 

                 * 無足輕重(Genuine but Insignificant Cause) 錯謬:舉出無足輕重的次要原因論證,遺漏真正的主因。 
                 * 例子:吸煙使香港空氣質(zhì)素每況愈下。 
                 * 解釋:導(dǎo)致香港空氣質(zhì)素差的主因是交通公具的廢氣和天氣情況。 

                 * 倒果為因(Wrong Direction) 錯謬:顛倒事件的因果關(guān)系。 
                 * 例子:癌癥導(dǎo)致吸煙 
                 * 解釋:吸煙才是癌癥的原因。 

                 * 復(fù)合原因(Complex Cause) 錯謬:只指出多個原因中的其中一個為事件主因。 
                 * 例子:你一日到晚都只是玩游戲機而不溫習(xí),難怪你考試成績那麼差。 
                 * 解釋:除了玩游戲機而不溫習(xí)外,還有其他原因,例如考試期間一時大意或者試題太難,但它們和玩游戲機一樣,不一定是主因。 

            論點缺失謬誤(Missing the Point) 

                 * 乞求/竊取論點(Begging the Question) 錯謬:以假定正確的論點得出結(jié)論。 
                 * 例子:我知道有上帝,因為《圣經(jīng)》是這樣說,而《圣經(jīng)》是不會錯,因為它是上帝寫的。 

                 * 不恰當(dāng)結(jié)論(Irrelevant Conclusion) 錯謬:提出作支持的論據(jù)主要支持其他結(jié)論。 
                 * 例子: 

                 * 稻草人謬誤(Straw Man) 錯謬:扭曲對方論據(jù)以攻擊之。 
                 * 例子:進化論說人是由猩猩演化而來。 
                 * 解釋:進化論只是說人和猩猩有共同祖先。 

            含糊不清謬誤(Fallacies of Ambiguity) 

                 * 含糊其辭(Equivocation) 錯謬:使用有多於一個含義的字眼。 
                 * 例子:甲:喇叭中學(xué)又發(fā)生學(xué)生毆斗事件。乙:噢!是九龍那所嗎?甲:&%^%$&%$#... 
                 * 解釋:甲這里沒有表明是新界喇叭,使乙誤會成九龍的喇叭書院。 

                 * 模棱兩可(Amphiboly) 錯謬:句子結(jié)構(gòu)含多種解釋方法。 
                 * 例子: 

                 * 重音謬誤(Accent) 錯謬:以重音強調(diào)某字眼或字句,達致其他意思。 
                 * 例子: 

            類目錯誤(Category Errors) 

                 * 構(gòu)成謬誤(Composition) 錯謬:以總體的某部份符合某條件推斷總體均符合某條件。 
                 * 例子: 

                 * 分割謬誤(Division) 錯謬:以總體符合某條件推斷總體的所有部份均符合某條件。 
                 * 例子: 

            不根據(jù)前題的推理(Non Sequitur) 

                 * 肯定後件(Affirming the Consequent) 錯謬:所有依此結(jié)構(gòu)的推論:若A則必定B;B,所以便A。 
                 * 例子:如果他在中環(huán),他一定在港島。因此如果他現(xiàn)在在港島,他一定在中環(huán)。 
                 * 解釋:在港島不一定要在中環(huán),可以在金鐘、灣仔、銅鑼灣等。因港島包含了以上各項。 

                 * 否定前件(Denying the Antecedent) 錯謬:所有依此結(jié)構(gòu)的推論:若A則必定B; 非A,所以非B。 
                 * 例子:如果他在中環(huán),他一定在港島。因此如果他現(xiàn)在不在中環(huán),那麼他一定不在港島。 
                 * 解釋:不在中環(huán),也可以在金鐘、灣仔、銅鑼灣等。因港島包含了以上各項。 

                 * 前後矛盾(Inconsistency) 錯謬:斷言兩件矛盾的事件都正確 

            posted @ 2009-04-30 13:02 OxFAN 閱讀(483) | 評論 (0)編輯 收藏

            (注:個人覺得這篇文章不錯故轉(zhuǎn)載了)

                 C++中的虛函數(shù)的作用主要是實現(xiàn)了多態(tài)的機制。關(guān)于多態(tài),簡而言之就是用父類型別的指針指向其子類的實例,然后通過父類的指針調(diào)用實際子類的成員函數(shù)。這種技術(shù)可以讓父類的指針有“多種形態(tài)”,這是一種泛型技術(shù)。所謂泛型技術(shù),說白了就是試圖使用不變的代碼來實現(xiàn)可變的算法。比如:模板技術(shù),RTTI技術(shù),虛函數(shù)技術(shù),要么是試圖做到在編譯時決議,要么試圖做到運行時決議。

            關(guān)于虛函數(shù)的使用方法,我在這里不做過多的闡述。大家可以看看相關(guān)的C++的書籍。在這篇文章中,我只想從虛函數(shù)的實現(xiàn)機制上面為大家 一個清晰的剖析。

            當(dāng)然,相同的文章在網(wǎng)上也出現(xiàn)過一些了,但我總感覺這些文章不是很容易閱讀,大段大段的代碼,沒有圖片,沒有詳細的說明,沒有比較,沒有舉一反三。不利于學(xué)習(xí)和閱讀,所以這是我想寫下這篇文章的原因。也希望大家多給我提意見。

            言歸正傳,讓我們一起進入虛函數(shù)的世界。

            虛函數(shù)表

            對C++ 了解的人都應(yīng)該知道虛函數(shù)(Virtual Function)是通過一張?zhí)摵瘮?shù)表(Virtual Table)來實現(xiàn)的。簡稱為V-Table。 在這個表中,主是要一個類的虛函數(shù)的地址表,這張表解決了繼承、覆蓋的問題,保證其容真實反應(yīng)實際的函數(shù)。這樣,在有虛函數(shù)的類的實例中這個表被分配在了 這個實例的內(nèi)存中,所以,當(dāng)我們用父類的指針來操作一個子類的時候,這張?zhí)摵瘮?shù)表就顯得由為重要了,它就像一個地圖一樣,指明了實際所應(yīng)該調(diào)用的函數(shù)。

            這里我們著重看一下這張?zhí)摵瘮?shù)表。在C++的標(biāo)準(zhǔn)規(guī)格說明書中說到,編譯器必需要保證虛函數(shù)表的指針存在于對象實例中最前面的位置(這是為了保證正確取到虛函數(shù)的偏移量)。 這意味著我們通過對象實例的地址得到這張?zhí)摵瘮?shù)表,然后就可以遍歷其中函數(shù)指針,并調(diào)用相應(yīng)的函數(shù)。

            聽我扯了那么多,我可以感覺出來你現(xiàn)在可能比以前更加暈頭轉(zhuǎn)向了。 沒關(guān)系,下面就是實際的例子,相信聰明的你一看就明白了。

            假設(shè)我們有這樣的一個類:

            class Base {

            public:

            virtual void f() { cout << "Base::f" << endl; }

            virtual void g() { cout << "Base::g" << endl; }

            virtual void h() { cout << "Base::h" << endl; }

            };

            按照上面的說法,我們可以通過Base的實例來得到虛函數(shù)表。 下面是實際例程:

            typedef void(*Fun)(void);

            Base b;

            Fun pFun = NULL;

            cout << "虛函數(shù)表地址:" << (int*)(&b) << endl;

            cout << "虛函數(shù)表 — 第一個函數(shù)地址:" << (int*)*(int*)(&b) << endl;

            // Invoke the first virtual function

            pFun = (Fun)*((int*)*(int*)(&b));

            pFun();

            實際運行經(jīng)果如下:(Windows XP+VS2003, Linux 2.6.22 + GCC 4.1.3)

            虛函數(shù)表地址:0012FED4

            虛函數(shù)表 — 第一個函數(shù)地址:0044F148

            Base::f

            通過這個示例,我們可以看到,我們可以通過強行把&b轉(zhuǎn)成int *,取得虛函數(shù)表的地址,然后,再次取址就可以得到第一個虛函數(shù)的地址了,也就是Base::f(),這在上面的程序中得到了驗證(把int* 強制轉(zhuǎn)成了函數(shù)指針)。通過這個示例,我們就可以知道如果要調(diào)用Base::g()和Base::h(),其代碼如下:

            (Fun)*((int*)*(int*)(&b)+0); // Base::f()

            (Fun)*((int*)*(int*)(&b)+1); // Base::g()

            (Fun)*((int*)*(int*)(&b)+2); // Base::h()

            這個時候你應(yīng)該懂了吧。什么?還是有點暈。也是,這樣的代碼看著太亂了。沒問題,讓我畫個圖解釋一下。如下所示:

            注意:在上面這個圖中,我在虛函數(shù)表的最后多加了一個結(jié)點,這是虛函數(shù)表的結(jié)束結(jié)點,就像字符串的結(jié)束符“\0”一樣,其標(biāo)志了虛函數(shù)表的結(jié)束。這個結(jié)束標(biāo)志的值在不同的編譯器下是不同的。在WinXP+VS2003下,這個值是NULL。而在Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3下,這個值是如果1,表示還有下一個虛函數(shù)表,如果值是0,表示是最后一個虛函數(shù)表。

            下面,我將分別說明“無覆蓋”和“有覆蓋”時的虛函數(shù)表的樣子。沒有覆蓋父類的虛函數(shù)是毫無意義的。我之所以要講述沒有覆蓋的情況,主要目的是為了給一個對比。在比較之下,我們可以更加清楚地知道其內(nèi)部的具體實現(xiàn)。

            一般繼承(無虛函數(shù)覆蓋)

            下面,再讓我們來看看繼承時的虛函數(shù)表是什么樣的。假設(shè)有如下所示的一個繼承關(guān)系:

            請注意,在這個繼承關(guān)系中,子類沒有重載任何父類的函數(shù)。那么,在派生類的實例中,其虛函數(shù)表如下所示:

            對于實例:Derive d; 的虛函數(shù)表如下:

            我們可以看到下面幾點:

            1)虛函數(shù)按照其聲明順序放于表中。

            2)父類的虛函數(shù)在子類的虛函數(shù)前面。

            我相信聰明的你一定可以參考前面的那個程序,來編寫一段程序來驗證。

            一般繼承(有虛函數(shù)覆蓋)

            覆蓋父類的虛函數(shù)是很顯然的事情,不然,虛函數(shù)就變得毫無意義。下面,我們來看一下,如果子類中有虛函數(shù)重載了父類的虛函數(shù),會是一個什么樣子?假設(shè),我們有下面這樣的一個繼承關(guān)系。

            為了讓大家看到被繼承過后的效果,在這個類的設(shè)計中,我只覆蓋了父類的一個函數(shù):f()。那么,對于派生類的實例,其虛函數(shù)表會是下面的一個樣子:

            我們從表中可以看到下面幾點,

            1)覆蓋的f()函數(shù)被放到了虛表中原來父類虛函數(shù)的位置。

            2)沒有被覆蓋的函數(shù)依舊。

            這樣,我們就可以看到對于下面這樣的程序,

            Base *b = new Derive();

            b->f();

            由b所指的內(nèi)存中的虛函數(shù)表的f()的位置已經(jīng)被Derive::f()函數(shù)地址所取代,于是在實際調(diào)用發(fā)生時,是Derive::f()被調(diào)用了。這就實現(xiàn)了多態(tài)。

            多重繼承(無虛函數(shù)覆蓋)

            下面,再讓我們來看看多重繼承中的情況,假設(shè)有下面這樣一個類的繼承關(guān)系。注意:子類并沒有覆蓋父類的函數(shù)。

            對于子類實例中的虛函數(shù)表,是下面這個樣子:

            我們可以看到:

            1) 每個父類都有自己的虛表。

            2) 子類的成員函數(shù)被放到了第一個父類的表中。(所謂的第一個父類是按照聲明順序來判斷的)

            這樣做就是為了解決不同的父類類型的指針指向同一個子類實例,而能夠調(diào)用到實際的函數(shù)。

            多重繼承(有虛函數(shù)覆蓋)

            下面我們再來看看,如果發(fā)生虛函數(shù)覆蓋的情況。

            下圖中,我們在子類中覆蓋了父類的f()函數(shù)。

            下面是對于子類實例中的虛函數(shù)表的圖:

            我們可以看見,三個父類虛函數(shù)表中的f()的位置被替換成了子類的函數(shù)指針。這樣,我們就可以任一靜態(tài)類型的父類來指向子類,并調(diào)用子類的f()了。如:

            Derive d;

            Base1 *b1 = &d;

            Base2 *b2 = &d;

            Base3 *b3 = &d;

            b1->f(); //Derive::f()

            b2->f(); //Derive::f()

            b3->f(); //Derive::f()

            b1->g(); //Base1::g()

            b2->g(); //Base2::g()

            b3->g(); //Base3::g()

            安全性

            每次寫C++的文章,總免不了要批判一下C++。這篇文章也不例外。通過上面的講述,相信我們對虛函數(shù)表有一個比較細致的了解了。水可載舟,亦可覆舟。下面,讓我們來看看我們可以用虛函數(shù)表來干點什么壞事吧。

            一、通過父類型的指針訪問子類自己的虛函數(shù)

            我們知道,子類沒有重載父類的虛函數(shù)是一件毫無意義的事情。因為多態(tài)也是要基于函數(shù)重載的。雖然在上面的圖中我們可以看到Base1的虛表中有Derive的虛函數(shù),但我們根本不可能使用下面的語句來調(diào)用子類的自有虛函數(shù):

            Base1 *b1 = new Derive();

            b1->f1(); //編譯出錯

            任何妄圖使用父類指針想調(diào)用子類中的未覆蓋父類的成員函數(shù)的行為都會被編譯器視為非法,所以,這樣的程序根本無法編譯通過。但在運行時,我們可以通過指針的方式訪問虛函數(shù)表來達到違反C++語義的行為。(關(guān)于這方面的嘗試,通過閱讀后面附錄的代碼,相信你可以做到這一點)

            二、訪問non-public的虛函數(shù)

            另外,如果父類的虛函數(shù)是private或是protected的,但這些非public的虛函數(shù)同樣會存在于虛函數(shù)表中,所以,我們同樣可以使用訪問虛函數(shù)表的方式來訪問這些non-public的虛函數(shù),這是很容易做到的。

            如:

            class Base {

            private:

            virtual void f() { cout << "Base::f" << endl; }

            };

            class Derive : public Base{

            };

            typedef void(*Fun)(void);

            void main() {

            Derive d;

            Fun pFun = (Fun)*((int*)*(int*)(&d)+0);

            pFun();

            }

            結(jié)束語

            C++這門語言是一門Magic的語言,對于程序員來說,我們似乎永遠摸不清楚這門語言背著我們在干了什么。需要熟悉這門語言,我們就必需要了解C++里面的那些東西,需要去了解C++中那些危險的東西。不然,這是一種搬起石頭砸自己腳的編程語言。

            posted @ 2009-04-30 11:02 OxFAN 閱讀(193) | 評論 (1)編輯 收藏

            2009年4月29日 #

            剛剛落戶cnblog,又來到了cppblog,這樣cnblog上的空間可能就要荒廢了,怪只能怪我沒有早發(fā)現(xiàn)cppblog。
            posted @ 2009-04-29 13:02 OxFAN 閱讀(153) | 評論 (0)編輯 收藏

            亚洲AV日韩精品久久久久| 久久久久久午夜成人影院| 无码人妻少妇久久中文字幕| 99久久国产亚洲高清观看2024| 香蕉aa三级久久毛片| 亚洲午夜久久久久妓女影院| 精品午夜久久福利大片| 亚洲精品无码久久久| 久久久久亚洲av无码专区导航| 国产精品久久久天天影视香蕉 | 精品国产乱码久久久久久呢| 久久精品国产网红主播| 久久强奷乱码老熟女网站| 99国产欧美久久久精品蜜芽 | 久久久精品国产sm调教网站| 国产999精品久久久久久| 久久精品国产亚洲AV香蕉| 国产精品丝袜久久久久久不卡| 亚洲va久久久噜噜噜久久| 精品久久久久国产免费| 成人国内精品久久久久影院| 久久午夜福利无码1000合集| 51久久夜色精品国产| 99久久久精品| 久久久久久久久久久| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 久久精品国产亚洲AV嫖农村妇女| 亚洲伊人久久综合影院| 久久中文字幕无码专区| 99久久国产免费福利| 99久久99久久精品国产| 日本福利片国产午夜久久| 97久久久精品综合88久久| 国产精品久久久久jk制服| 婷婷五月深深久久精品| 亚洲国产精品无码久久一区二区 | 精品999久久久久久中文字幕| 少妇久久久久久被弄高潮| 日韩久久久久久中文人妻 | 国产A级毛片久久久精品毛片| 久久久久久久免费视频|