回覆列表
  • 1 # 使用者6301823778307

    因為C++的class真的只是個struct,只不過C++編譯器會在編譯期對它做一些“魔改”動作而已。早年,諸如遊戲業的精靈抽象、unix系的“一切皆檔案”等設計思想,都是用C乃至彙編表現出來的。正是這些思想啟發並引導了後來的面向物件熱潮。對C來說,struct可以放任何它支援的資料型別。包括函式指標——後來C++所謂的虛擬函式表,很多編譯器的實現,就是一個指向另一個全域性結構體的指標,這個全域性結構體裡面是一條一條的函式指標,指向對應類過載後的所謂“虛擬函式”。至於各種所謂的成員函式,實際上就是些第一個引數是classXX型別的this指標的普通函式。換言之,struct本身已經足以支援面向物件程式設計執行期需要的一切了;現在,我們只需要增加一些新的語法約定,使得編譯器可以幫助使用者自動維護這些瑣碎細節就行了——這正是 Bjarne Stroustrup當年搞Cfront的設計思路: 先把C++程式碼自動魔改到C,然後呼叫C編譯器完成編譯。後期雖然有了直接支援c++的編譯器(因為在cfront中加入異常支援失敗),但編譯器關於struct的處理並沒有本質的不同。於是,所謂class,其實就是加了某些外部支援的struct——除了編譯期可能會被編譯器魔改的面目全非外,它和普通struct毫無差別。這個支援一般來說應該是這樣的(但並不禁止編譯器廠商選擇其他方案):1、對普通成員函式,為它自動新增this引數,並在呼叫它時,自動把 obj.method() 轉換成 method(obj)格式;並識別出函式中涉及的、沒有顯式使用this的成員變數、為它加上this。除此之外,別的什麼都不用做。2、對虛擬函式,需要為繼承鏈上的每個類產生一個全域性結構體,在這個結構體裡按次序安排指向該類所有虛擬函式的指標,這就是虛擬函式表;然後在類裡新增一個指向屬於自己的虛擬函式表的指標。那麼,當用戶呼叫某個物件的第N個虛擬函式時,到虛擬函式表查詢並獲取第N個函式指標指向的內容;然後類似呼叫普通成員函式一樣,把 obj.method() 轉換成 method(obj)格式,多型就實現了。當然,除此之外,還要在編譯時執行許可權檢查,避免非法訪問類的protect/private成員(struct預設許可權是public,class是private);以及另外一些瑣碎工作。所以你看,c++的類歸根結底,它就是個C語言的struct。只是(相當於)在編譯期做了些預處理而已——只要你在裡面聲明瞭成員函式,就會自動觸發預處理,從而實現“自動魔改你所定義的資料結構,使其支援OO諸要素”功能。那麼,除了讓C程式碼共用C++裡面定義的struct這個特殊場景外(想了解這類能相容C的資料型別,可搜尋 POD型別),你說還有什麼理由禁止struct擁有成員函式呢?

  • 中秋節和大豐收的關聯?
  • 世界十大禁用槍支有什麼?