C++設計模式:面向對象的八大設計原則之四

里氏替換原則(Liskov Substitution Principle,LSP)是面向對象設計中的一個重要原則,它指出子類必須能夠替換它的基類,并且程序的行為不會發生改變。也就是說,在任何使用基類對象的地方,都可以透明地使用其子類對象。繼承不僅是代碼復用的手段,更重要的是表達了類型的抽象,子類是對基類的一種特殊化。

下面通過幾個 C++ 代碼示例來詳細講解里氏替換原則。

示例一:簡單的繼承與替換

首先,我們定義一個基類 Shape 表示形狀,然后派生出子類 Rectangle(矩形)和 Square(正方形)。

#include <iostream>// 基類:形狀class Shape {public:virtual double area() const = 0;virtual ~Shape() {}};// 子類:矩形class Rectangle : public Shape {private:double width;double height;public:Rectangle(double w, double h) : width(w), height(h) {}double area() const override {return width * height;}};// 子類:正方形class Square : public Shape {private:double side;public:Square(double s) : side(s) {}double area() const override {return side * side;}};// 計算形狀面積的函數void printArea(const Shape& shape) {std::cout << "Area: " << shape.area() << std::endl;}int main() {Rectangle rect(3, 4);Square square(5);// 可以用子類對象替換基類對象printArea(rect);printArea(square);return 0;} ???

代碼解釋

Shape 是一個抽象基類,定義了純虛函數 area(),用于計算形狀的面積。

Rectangle 和 Square 是 Shape 的子類,分別實現了 area() 函數。

printArea 函數接受一個 Shape 類型的引用作為參數,在 main 函數中,我們可以將 Rectangle 和 Square 對象傳遞給 printArea 函數,這體現了子類可以替換基類的特性。

示例二:違反里氏替換原則的情況

有時候,如果子類的行為與基類的預期行為不一致,就會違反里氏替換原則。例如,我們對上面的 Rectangle 和 Square 類進行修改,添加 setWidth 和 setHeight 方法。

#include <iostream>// 基類:矩形class Rectangle {protected:double width;double height;public:Rectangle(double w, double h) : width(w), height(h) {}virtual void setWidth(double w) { width = w; }virtual void setHeight(double h) { height = h; }double area() const {return width * height;}};// 子類:正方形class Square : public Rectangle {public:Square(double s) : Rectangle(s, s) {}void setWidth(double w) override {width = w;height = w;}void setHeight(double h) override {width = h;height = h;}};// 調整矩形尺寸并打印面積的函數void resizeAndPrint(Rectangle& rect) {rect.setWidth(5);rect.setHeight(10);std::cout << "Area: " << rect.area() << std::endl;}int main() {Rectangle rect(3, 4);Square square(5);// 對于矩形,預期結果是 5 * 10 = 50resizeAndPrint(rect);// 對于正方形,結果不符合預期,因為正方形的寬和高總是相等的resizeAndPrint(square);return 0;}

代碼解釋

在這個例子中,Square 類繼承自 Rectangle 類,但是 Square 類的 setWidth 和 setHeight 方法會同時修改寬和高,這與 Rectangle 類的預期行為不一致。

resizeAndPrint 函數期望傳入的 Rectangle 對象可以獨立地設置寬和高,但是當傳入 Square 對象時,結果不符合預期,這就違反了里氏替換原則。

總結

里氏替換原則強調了繼承關系中類型的兼容性和行為的一致性。在設計類和繼承體系時,要確保子類能夠完全替換基類,并且不會破壞程序的正確性。如果子類的行為與基類的預期行為不一致,就可能需要重新考慮類的設計,例如使用組合而不是繼承。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79278.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79278.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79278.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡通信領域的基礎或流行協議

一、TCP(傳輸控制協議) 1. 宏觀介紹 TCP:全稱“Transmission Control Protocol”——傳輸控制協議,是互聯網最基礎的傳輸協議之一。傳輸層協議,提供面向連接、可靠的字節流傳輸服務。它通過三次握手建立連接、四次揮手斷開連接,確保數據有序、完整地傳輸作用:讓兩個設備…

【教學類-34-10】20250503(通義萬相)4*3蝴蝶拼圖(圓形、三角、正方、半圓的凹凸小塊+參考圖灰色)

背景需求 2023年從網站上搜索拼圖代碼,陸續改良了圓形、三角形、菱形凹凸) 【教學類-34-05】20230425拼圖(“圓角”凹凸拼圖)3*4格子(中班主題《個別化拼圖》偏美術)_拼圖的槽叫什么形狀-CSDN博客文章瀏覽閱讀1.1k次。【教學類-34-05】20230425拼圖(“圓角”凹凸拼圖)…

bellard.org? : QuickJS 如何使用 qjs 執行 js 腳本

參閱上一篇&#xff1a;Fabrice Bellard&#xff08;個人網站&#xff1a;?bellard.org?&#xff09;介紹 Fabrice Bellard&#xff08;個人網站&#xff1a;?bellard.org?&#xff09;是計算機領域最具影響力的程序員之一&#xff0c;其貢獻跨越多個技術領域并持續推動開…

數據結構---

案例一 1.隨機生成n個工人工時&#xff0c;100以內&#xff0c;工號分別為2021101到2021100n 2.以工時數為關鍵字分別使用選擇排序、冒泡排序、插入排序進行升序排序。 3.把排序后的結果輸出&#xff0c;包括工號工時數 4.比較三種算法對相同的n值數組排序所花的時間 代碼如下&…

Python硬核革命:從微控制器到FPGA的深度開發指南

1. 重新定義硬件開發:Python的顛覆性突破 傳統硬件開發長期被C/C++和Verilog/VHDL統治,但Python正通過兩條路徑改變這一格局: 1.1 微控制器領域的MicroPython革命 完整Python 3.4語法支持,運行在資源受限的MCU上(最低要求:64KB ROM,16KB RAM) 直接內存訪問能力,突破…

基于springboot+vue的寵物共享平臺

開發語言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服務器&#xff1a;tomcat7數據庫&#xff1a;mysql 5.7數據庫工具&#xff1a;Navicat12開發軟件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.3.9 系統展示 寵物寄養管理 寵…

day 11 超參數調整

一、內參與外參&#xff08;超參數&#xff09; 內參是模型為了適應訓練數據而自動調整的&#xff0c;是模型內部與訓練數據緊密相關的因素&#xff0c;不同的訓練數據會導致模型學習到不同的參數值&#xff0c;這些參數在模型訓練完成后就固定下來。 超參數是在模型訓練前需…

快速搭建對象存儲服務 - Minio,并解決臨時地址暴露ip、短鏈接請求改變瀏覽器地址等問題

其他文章 服務容錯治理框架resilience4j&sentinel基礎應用---微服務的限流/熔斷/降級解決方案-CSDN博客 conda管理python環境-CSDN博客 快速搭建對象存儲服務 - Minio&#xff0c;并解決臨時地址暴露ip、短鏈接請求改變瀏覽器地址等問題-CSDN博客 大模型LLMs的MCP入門-…

樸素貝葉斯分類器

樸素貝葉斯分類器 樸素貝葉斯是一種基于密度估計的分類算法&#xff0c;它利用貝葉斯定理進行預測。該算法的核心假設是在給定類別的情況下&#xff0c;各個特征之間是條件獨立的&#xff0c;盡管這一假設在現實中通常不成立&#xff0c;但樸素貝葉斯分類器依然能夠生成對有偏…

在 Trae CN IDE 中配置 Python 3.11的指南

在 Trae CN IDE 中配置 Python 3.11的指南 下載 python 3.11 安裝 Python 3.11 首先&#xff0c;我們需要確保安裝了 Python 3.11。可以從Python 官方網站下載適合你操作系統的版本。 鏈接 如果你已經安裝了 Python 3.11&#xff0c;可以通過以下命令確認&#xff1a; 文…

MQTT 協議與 HTTP 協議的區別

在現代的網絡通信中&#xff0c;MQTT 協議和 HTTP 協議都扮演著重要的角色&#xff0c;但它們有著不同的特點和適用場景。下面我們就從多個方面來詳細探討它們之間的區別。 一.協議設計理念 1. MQTT 協議 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;即…

Postgresql源碼(145)優化器nestloop參數化路徑評估不準問題分析

相關 《Postgresql源碼&#xff08;133&#xff09;優化器動態規劃生成連接路徑的實例分析》 1 問題 最近遇到一個問題&#xff0c;評估行數和真實行數存在較大差距&#xff0c;導致計劃不準的問題。 nestloop內表評估是根據外表的參數來的。因為外表驅動表每取一條&#xff…

HTML與CSS實現風車旋轉圖形的代碼技術詳解

在前端開發中&#xff0c;HTML和CSS是構建網頁的基礎技術。通過巧妙運用HTML的結構搭建和CSS的樣式控制&#xff0c;我們能夠實現各種精美的視覺效果。本文將對一段實現旋轉圖形效果的HTML和CSS代碼進行詳細解讀&#xff0c;剖析其中的技術要點。 一、運行效果 HTML與CSS實現風…

linux下,ollama會把模型文件保存在哪里?

文章目錄 運行ollama,有兩種形式,估計得分開討論首先是使用自動啟動的ollama:先跑個“小一點的大模型”但是現在模型文件存在哪兒呢?運行ollama,有兩種形式,估計得分開討論 我們用兩種方式,來運行ollama。 首先是使用自動啟動的ollama: ps -aux | grep ollama系統自…

鼎訊信通 智能通信干擾設備:多頻段多模態信號壓制解決方案

在萬物互聯時代&#xff0c;通信安全已成為現代社會的核心基礎設施防護重點。面對日益復雜的電磁環境挑戰&#xff0c;新一代智能通信干擾設備通過技術創新實現了信號壓制能力的革命性突破。本文將深入解析該設備的八大核心功能與技術特性&#xff0c;展現其在商業通信保障、工…

【2025軟考高級架構師】——案例分析總結(13)

摘要 本文對2025年軟考高級架構師的考綱及案例分析進行了總結。內容涵蓋系統規劃、架構設計、系統建模、安全架構、可靠性分析、大數據架構等多方面知識點&#xff0c;還涉及軟件質量特性、系統流程圖與數據流圖、嵌入式系統架構、分布式系統設計等考查內容&#xff0c;詳細列…

js單調棧解題模板

模板 function solve(arr) {const stack [];const result new Array(arr.length).fill(默認值);for (let i 0; i < arr.length; i) {while (stack.length && 比較條件(arr[i], arr[棧頂])) {const top stack.pop();result[top] 計算結果(i, top); }stack.push…

[藍橋杯真題題目及解析]2025年C++b組

移動距離&#xff08;填空&#xff09;** 小明初始在二維平面的原點&#xff0c;他想前往坐標 (233,666)。在移動過程中&#xff0c;他只能采用以下兩種移動方式&#xff0c;并且這兩種移動方式可以交替、不限次數地使用&#xff1a; 水平向右移動&#xff0c;即沿著 x 軸正方…

【ICMP協議深度解析】從網絡診斷到安全實踐

目錄 前言技術背景與價值當前技術痛點解決方案概述目標讀者說明 一、技術原理剖析核心概念圖解核心作用講解關鍵報文類型說明協議版本對比 二、實戰演示環境配置要求核心實驗實現實驗1&#xff1a;標準ping流程實驗2&#xff1a;traceroute路徑發現實驗3&#xff1a;自定義ICMP…

安卓基礎(懸浮窗分級菜單和彈窗)

initializeViews() 初始化 把全部的按鈕都弄出來 // 主菜單按鈕ImageButton mainButton floatingMenuView.findViewById(R.id.main_button);// 二級菜單按鈕subButtons new ImageButton[3];subButtons[0] floatingMenuView.findViewById(R.id.sub_button_1);subButtons[1]…