跳轉到內容

C++ 程式設計:程式語言正規化

來自華夏公益教科書,開放書籍,為開放的世界

程式設計正規化

[編輯 | 編輯原始碼]

一個 程式設計正規化 是一個基於不同概念的程式設計模型,它塑造了程式設計師設計、組織和編寫程式的方式。一個 多正規化程式語言 允許程式設計師選擇特定的單個方法或混合不同程式設計正規化的部分。C++ 作為一種多正規化程式語言,支援使用過程式或面向物件程式設計的單個或混合方法,並混合使用泛型甚至函數語言程式設計概念。

程序式程式設計

[編輯 | 編輯原始碼]

程序式程式設計 可以定義為 指令式程式設計 的一種子型別,它是一種基於過程呼叫概念的程式設計正規化,其中 語句 被結構化到過程(也稱為子例程或函式)中。過程呼叫是模組化的,並受範圍限制。一個過程式程式由一個或多個 模組 組成。每個模組由一個或多個 子程式 組成。模組可能包含過程、函式、子例程或方法,具體取決於程式語言。過程式程式可能具有多個級別或範圍,子程式在其他子程式內定義。每個範圍可以包含在外部範圍中不可見的名稱。

程序式程式設計與簡單的順序程式設計相比,提供了許多優勢,因為過程式程式碼

  • 更易於閱讀和維護
  • 更靈活
  • 促進良好程式設計的實踐
  • 允許模組以 程式碼庫 的形式再次使用。

注意
如今,很少看到 C++ 嚴格使用程序式程式設計正規化,它主要只在小型演示或測試程式中使用。

靜態型別

[編輯 | 編輯原始碼]

型別 指的是計算機語言如何處理其變數,以及它們如何透過 型別 區分。變數是程式在執行期間使用的值。這些值可以改變;它們是變數,因此得名。靜態型別 通常會導致執行速度更快的編譯程式碼。當編譯器知道正在使用的確切型別時,它可以生成更容易執行正確操作的機器程式碼。在 C++ 中,變數需要在使用之前定義,以便編譯器知道它們的型別,因此是靜態型別的。非靜態型別的語言稱為 動態型別

靜態型別通常可以在編譯時更可靠地發現型別錯誤,從而提高編譯程式的可靠性。簡而言之,這意味著“圓形銷釘不能放入方形孔中”,因此編譯器將在型別導致歧義或不相容使用時報告它。但是,程式設計師對型別錯誤的普遍程度以及靜態型別將捕獲多少已編寫錯誤存在分歧。靜態型別支持者認為,程式在進行型別檢查後會更加可靠,而動態型別支持者則指出了已證明可靠的動態程式碼和小型錯誤資料庫。因此,靜態型別的價值隨著型別系統強度的增加而增加。

靜態型別系統比約束較不強大的語言結構更能約束強大的語言結構的使用。這使得強大的結構更難使用,因此將選擇“適合問題的正確工具”的負擔放在程式設計師的肩上,否則他們可能傾向於使用可用的最強大的工具。選擇過於強大的工具可能會導致額外的效能、可靠性或正確性問題,因為對於可以從強大的語言結構中預期得到的屬性存在 理論限制。例如,不加選擇地使用 遞迴全域性變數 會導致有據可查的不利影響。

靜態型別允許構建不太可能被使用者意外誤用的庫。這可以用作傳達庫開發人員意圖的附加機制。

型別檢查

[編輯 | 編輯原始碼]

型別檢查 是驗證和強制型別約束的過程,這可以在編譯時或執行時發生。編譯時檢查,也稱為 靜態型別 檢查,由編譯器在編譯程式時執行。執行時檢查,也稱為 動態型別檢查,由程式在執行時執行。如果型別系統確保型別之間的轉換必須有效或導致錯誤,則稱程式語言為 強型別。另一方面,弱型別 語言不提供此類保證,通常允許型別之間的自動轉換,而這些轉換可能沒有用武之地。C++ 介於兩者之間,允許自動型別轉換和程式設計師定義的轉換,允許在解釋一種型別為另一種型別時幾乎完全靈活。將一種型別的變數或表示式轉換為另一種型別稱為 型別轉換

面向物件程式設計

[編輯 | 編輯原始碼]

面向物件程式設計 可以被視為程序式程式設計的擴充套件,其中程式由稱為 物件 的單個單元的集合組成,這些單元具有不同的目的和功能,對 實現 的依賴有限或沒有依賴。例如,汽車就像一個物件;它可以將你從 A 點帶到 B 點,而無需瞭解汽車使用的是哪種發動機或發動機的工作原理。面向物件的語言通常提供一種方法來 記錄 物件可以做什麼和不能做什麼,就像駕駛汽車的說明書一樣。

物件和類

[編輯 | 編輯原始碼]

一個物件是由成員方法組成的。成員(也稱為資料成員特徵屬性特性)描述了該物件。方法通常描述與特定物件相關的操作。可以將物件視為名詞,其成員視為描述該名詞的形容詞,其方法視為該名詞可以執行的動詞。

例如,一輛跑車就是一個物件。它的成員可能是它的高度、重量、加速度和速度。物件的成員只是儲存有關該物件的資料。跑車的某些方法可以是“駕駛”、“停車”、“比賽”等。方法只有與跑車相關聯才真正有意義,成員也是如此。

讓我們構建跑車物件的“藍圖”稱為。類不會告訴我們跑車的速度或顏色,但它確實告訴我們跑車將有一個代表速度和顏色的成員,並且它們將分別是數字和單詞。類還為我們制定了方法,告訴汽車如何停車和駕駛,但這些方法僅憑藍圖無法採取任何行動——它們需要一個物件才能產生影響。

C++ 中的類與 C 中的結構相同;區別在於類使用者可以透過私有選項隱藏資料。在 C++ 中,物件是類的例項,它被視為一個內建變數,它儲存許多值。

封裝,即資訊隱藏(對使用者而言)的原則,是隱藏類資料結構並允許透過公共介面更改資料的過程,在公共介面中,傳入的值會經過有效性檢查,因此它不僅允許隱藏物件中的資料,還允許隱藏行為。這可以防止介面的客戶端依賴於可能在將來發生變化的實現部分,從而使這些更改更容易進行,即無需更改客戶端。在現代程式語言中,資訊隱藏的原則以多種方式體現出來,包括封裝和多型性。

繼承描述了兩種(或更多種)型別的物件之間的關係,其中一種被認為是另一種的“子型別”或“子類”;因此,“子類”物件被認為繼承了父類的特性,允許共享功能。這使得程式設計師可以重用或減少程式碼,並簡化軟體的開發和維護。

繼承通常也被認為包括子型別化,其中一種型別的物件被定義為另一種型別的更專門的版本(參見里氏替換原則),但非子型別化繼承也是可能的。

繼承通常透過描述以繼承層次結構(也稱為繼承鏈)排列的來表示,繼承層次結構是由它們的繼承關係建立的樹狀結構。

例如,可以建立一個名為“哺乳動物”的變數類,它具有進食、繁殖等特徵;然後定義一個子型別“貓”,它繼承了這些特徵而無需顯式地對其進行程式設計,同時添加了“追逐老鼠”等新特徵。這使得不同型別的物件的共效能夠表達一次並多次重複使用。

在 C++ 中,我們可以擁有與其他類相關的類(一個類可以透過一個更舊的、預先存在的來定義)。這導致了新類具有舊類所有功能的情況,並且還引入了自己的特定功能。我們在這裡指的是派生,其中一個給定類是另一個類,而不是組合,其中一個給定類包含另一個類。

當我們討論類(和結構)繼承時,將進一步解釋此 OOP 屬性,請參閱本書的類繼承部分

如果想要同時使用多個完全正交的層次結構,例如允許“貓”從“卡通人物”和“寵物”以及“哺乳動物”繼承,那麼我們正在使用多重繼承

多重繼承
[編輯 | 編輯原始碼]

多重繼承是指一個類可以繼承兩個或多個類的屬性(分別稱為基類、父類、祖先類或超類)的過程。

注意
在一些類似的語言中,多重繼承以多種方式受到限制,以保持語言的簡單性,例如只允許從一個真實類和多個“介面”繼承,或者完全不允許多重繼承。C++ 將多重繼承的全部功能交給了程式設計師,但它很少需要,並且(與大多數技術一樣)如果使用不當會導致程式碼變得複雜。由於 C++ 對多重繼承的處理方式,C++ 不需要其他語言設施來處理通常在其他面嚮物件語言中稱為“介面”、“特徵”或“mixin”的特殊語言結構,因為 C++ 的類本身已經提供了這種功能。

本書的C++ 類繼承部分將更詳細地介紹這一點。

多型性
[編輯 | 編輯原始碼]

多型性允許為多個相關但不同的目的重複使用單個名稱。多型性的目的是允許為一個通用類使用一個名稱。根據資料的型別,將執行通用情況的特定例項。

多型性的概念更為廣泛。每次使用具有相同名稱但實現不同的兩個函式時,就會存在多型性。它們也可以在介面方面有所不同,例如,透過採用不同的引數。在這種情況下,選擇要執行哪個函式是透過過載解析來完成的,並且在編譯時完成,因此我們將其稱為靜態多型性

動態多型性將在類部分中深入介紹,我們將討論它在派生類中重新定義方法時的使用。


泛型程式設計

[編輯 | 編輯原始碼]

泛型程式設計多型性是一種程式設計風格,它強調允許單個值採用不同的型別作為技術,只要保持某些約定,例如子型別簽名。簡單來說,泛型程式設計是基於尋找高效演算法的最抽象表示。模板普及了泛型的概念。模板允許在不考慮最終將使用它的型別的情況下編寫程式碼。模板在標準模板庫 (STL)中定義,泛型程式設計是在 STL 中引入 C++ 的。

自由格式

[編輯 | 編輯原始碼]

自由格式指的是程式設計師如何編寫程式碼。基本上,除了 C++ 的語義規則之外,沒有關於如何選擇編寫程式的規則。只要是合法的 C++,任何 C++ 程式都應該可以編譯。

C++ 的自由格式特性被一些程式設計師用來編寫混淆的 C++ 程式碼(專門編寫起來難以理解的程式碼)(取決於你的觀點)。在正確的上下文中,這也可以被視為一種工藝展示(非功能性但對語言的藝術性控制),但總的來說,混淆的使用只被認為是一種有用的原始碼安全機制,它確保原始碼更難以被第三方有意地分析、複製或使用。透過對編譯器有足夠的瞭解,原始碼也可以被設計為在其編譯後的形式中保留“水印”,這些“水印”將允許將其追溯到原始來源。

華夏公益教科書