cpp中的繼承

一、繼承概念

在cpp中,封裝、繼承、多態是面向對象的三大特性。這里的繼承就是允許已經存在的類(也就是基類)的基礎上創建新類(派生類或者子類),從而實現代碼的復用。

如上圖所示,Person是基類,Stu與Tea是派生類,Stu與Tea分別繼承了基類中的對象,同時也有自己的類對象。


1.1派生類對基類的修改

派生類對象可以賦值給基類對象、基類指針、基類引用,這里的賦值只是把派生類中原本繼承于父類的類對象賦值回去,對于派生類對象自己的類對象不會賦值。但是基類對象不能賦值給派生類對象。

如上圖,派生類只能將基類中原有的(或者說繼承過來的)_name和_gender賦值給父類,其余的無法賦值,如果是引用或指針,也是將派生類中基類對應的對象引用給或地址傳給基類,基類修改時,子類也會受影響。

如上圖,代碼驗證。注意,以上代碼是在public繼承時才會生效,如果換成protected時代碼就會報錯,protected繼承下來的父類對象就是protected而非public,不支持修改的,private繼承同理。


1.2父子類類成員變量、函數重名

當父類類成員變量名與子類成員變量名沖突時,默認時優先使用子類的。其實子類中也繼承了父類中的重名變量,只不過將其隱藏,可以通過指定類成員名::變量名的方式訪問。

再提一點,如果子類中沒有實現Print函數而是依靠父類中的Print函數,那么打印結果會是這樣的,如下圖。

這是因為返回給父類的是一個Person類型的this指針,解引用訪問的就是Person類中的_val.


當存在同名的函數名時,子類會調用自身的函數,也可以通過類名指定的方式進行訪問。


如上圖,這里A::func與B::func關系是隱藏,注意與函數重載區分(函數重載條件是同一作用域內函數名相同,參數列表不同構成重載)。


1.3派生類的默認成員函數

#include <iostream>
using namespace std;
class Person {
public://構造函數Person() :_name("張三") {cout << "Person()" << endl;}//析構函數~Person() {cout << "~Person()" << endl;}//拷貝構造Person(const Person& p1):_name(p1._name) {cout << "Person(copy construct)" << endl;}Person& operator=(const Person& p1) {cout << "operator=" << endl;if (this != &p1) {this->_name = p1._name;}return *this;}public:string _name;
};class Son :public Person {
public:Son(const char* name = "", const string id = "111"):_id(id){}void display() {cout << _name << " " << _id << endl;}
private:string _id;
};int main() {Son s1;s1.display();return 0;
}

子類繼承父類時會調用父類的構造函數來初始化繼承過來的成員,然后子類在初始化自己的成員,同理對于析構、拷貝構造、賦值重載等都是同理。

如上圖,s1會對繼承的成員調用其對應的Person類的構造函數,當然,這也是我沒有自定義時會調用父類的構造函數對其進行構造。

那么如何進行自定義構造_name呢?

如上圖所示,通過son的構造函數對s1進行實例化構造,但是對于從父類繼承下來的_name進行自定義時需要注意的是,在初始化_name時我們不能通過直接初始化的方式進行構造(如38行代碼,這是錯誤的),而是通過父類的構造函數對父類成員進行初始化。在上圖中也可以看見代碼在初始化列表時(代碼36行)就會調用父類的構造函數對_name進行初始化。

當然,也可以不自定義,此時_name就調用父類默認的構造函數對其進行初始化(前提是父類要有全缺省的構造函數,不然代碼就會報錯)。也可以使用初始化匿名對象的方式完成。

如上圖所示,同時也要在父類中定義相對應的構造函數類型。

實現子類對象的拷貝構造函數

如上圖,在實現子類的拷貝構造函數時,可以用子類類型的s來實例化Person,(這就是切片:父類可以提取子類中從父類繼承來的_name進行初始化通過參數來初始化基類成員)

實現子類對象的賦值重載函數

如上圖,實現子類對象的賦值重載函數時需要指明具體是哪一個重載函數,否則就會出現死循環,因為子類和父類出現同名函數時會優先調用子類的函數。代碼第61行將Son類對象s進行切片,然后調用父類Person的重載函數將s中父類的部分切給Person完成賦值重載。

1.4繼承與友元的關系

如上圖所示,父類A的友元函數為display,子類B繼承了父類A,此時友元函數只能訪問子類的公開成員,對于受保護和私有的則無法訪問。

1.5繼承與靜態成員

如上圖,父類A中定義的靜態成員變量在整個繼承體系中都是存在的。

1.6菱形繼承

如下圖,A是B和C的父類,D又同時繼承了B和C,此時D中含有基類成員_d和父類B(_b)和父類C(_c),同時B和C又同時含有A(_a),因此我們在訪問_a時需要指定類域。

在上述圖中可見,在開辟空間時,內存中64~68是父類B的空間,其中存放了B::_a和B::_b,對應的值就是1和3;而6C~70是父類C的空間,其中存放的就是C::_a和C::_C,對應的值就是2和4,最后一個位置就是D::_d。

如上圖,整個44~54是類對象D的空間。

造成代碼冗余與二義性問題

在上述代碼中,子類D會同時存儲了兩份A的繼承,分別是繼承B和C的,這個就造成了代碼冗余與內存消耗;其次當D訪問A中成員時必須要指定具體哪個類中的(無法通過d._a方式訪問)。解決方法就是虛擬繼承。


如上圖,通過虛擬繼承的方法可以直接訪問d._a,其實這里的B和C共享同一分A的繼承,也就是說代碼第91和92行對_a的修改是對同一個對象的修改(這一點在代碼運行過程中可以看出)。

如上圖所示,不難發現雖然_a是類中共享的一份區域,但是C和B區域與非虛擬繼承相比又多出一塊區域(如上圖中綠色區域所示)。在分析內存時,0x0078FEAC指向的位置是0x00929bf4,0x0078FEC0指向的位置是0x00929c00,其內存圖如下圖所示

如上圖所示,雖然0x00929bf4與0x00929c00指向的位置內容為空,但是其后一個位置的0000000c從十六進制轉換為十進制剛好是12,其實這也就是C到_a的偏移量,這個表叫做虛基表,而只想虛機表的指針叫做虛機表指針。

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

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

相關文章

【QT】QLinearGradient 線性漸變類簡單使用教程

目錄 0.簡介 1&#xff09;qtDesigner中 2&#xff09;實際執行 1.功能詳述 3.舉一反三的樣式 0.簡介 QLinearGradient 是 Qt 框架中的一個類&#xff0c;用于定義線性漸變效果&#xff08;通過樣式表設置&#xff09;。它可以用來填充形狀、背景或其他圖形元素&#xff0…

前端項目配置 Nginx 全攻略

在前端開發中&#xff0c;項目開發完成后&#xff0c;如何高效、穩定地將其部署到生產環境是至關重要的一步。Nginx 作為一款輕量級、高性能的 Web 服務器和反向代理服務器&#xff0c;憑借其出色的性能和豐富的功能&#xff0c;成為了前端項目部署的首選方案。本文將詳細介紹在…

網絡安全學習-常見web漏洞的滲xxx透以及防護方法

滲XX透測試 弱口令漏洞 漏洞描述 目標網站管理入口&#xff08;或數據庫等組件的外部連接&#xff09;使用了容易被猜測的簡單字符口令、或者是默認系統賬號口令。 滲XX透測試 如果不存在驗證碼&#xff0c;則直接使用相對應的弱口令字典使用burpsuite 進行爆破如果存在驗證…

網絡安全 機器學習算法 計算機網絡安全機制

&#xff08;一&#xff09;網絡操作系統 安全 網絡操作系統安全是整個網絡系統安全的基礎。操作系統安全機制主要包括訪問控制和隔離控制。 訪問控制系統一般包括主體、客體和安全訪問政策 訪問控制類型&#xff1a; 自主訪問控制強制訪問控制 訪問控制措施&#xff1a; 入…

2025網絡安全等級測評報告,信息安全風險評估報告(Word模板)

一、概述 1.1工作方法 1.2評估依據 1.3評估范圍 1.4評估方法 1.5基本信息 二、資產分析 2.1 信息資產識別概述 2.2 信息資產識別 三、評估說明 3.1無線網絡安全檢查項目評估 3.2無線網絡與系統安全評估 3.3 ip管理與補丁管理 3.4防火墻 四、威脅細類分析 4.1威脅…

Ubuntu22.04系統安裝Anaconda、CUDA和CUDNN

之前一直在Windows系統下使用Anaconda和CUDA加速&#xff0c;最近需要復現一個算法&#xff0c;文檔里面有Linux系統conda構建環境的教程。 本篇博文參考博文&#xff0c;記錄自己安裝的過程&#xff0c;便于以后需要。 目錄 1.Anaconda1.1 安裝包下載1.2 安裝軟件1.3 更新cond…

微信小程序調用火山方舟(字節跳動火山引擎)中的DeepSeek大模型

一、注冊火山引擎賬號&#xff0c;創建API Key和model&#xff08;接入點ID&#xff09; 1.注冊并登陸火山引擎賬號&#xff0c;網址為&#xff1a;https://console.volcengine.com/ 2.根據登陸后的頁面提示進行實名認證&#xff0c;實名認證后才能創建API Keyt和創建接入點。…

藍橋杯之日期題

文章目錄 1.藍橋杯必備知識點2. 題型13.需求2 1.藍橋杯必備知識點 藍橋杯是一個面向全國高校計算機相關專業學生的學科競賽&#xff0c;涵蓋多個賽道&#xff0c;常見的有軟件類&#xff08;如 C/C 程序設計、Java 軟件開發、Python 程序設計&#xff09;和電子類&#xff08;…

muduo網絡庫2

Muduo網絡庫&#xff1a;底層實質上為Linux的epoll pthread線程池&#xff0c;且依賴boost庫。 muduo的網絡設計核心為一個線程一個事件循環&#xff0c;有一個main Reactor負載accept連接&#xff0c;然后把連接分發到某個sub Reactor(采用輪詢的方式來選擇sub Reactor)&…

WinSCP 連接到 Ubuntu 虛擬機

要使用 WinSCP 連接到 Ubuntu 虛擬機&#xff0c;一般采用 SFTP 或 SCP 協議進行文件傳輸。以下是詳細步驟&#xff1a; 1. 確保虛擬機網絡可訪問 首先&#xff0c;你的 Ubuntu 虛擬機需要允許外部訪問&#xff1a; 如果使用 NAT 網絡&#xff1a;需要設置端口轉發&#xff0…

redis小記

redis小記 下載redis sudo apt-get install redis-server redis基本命令 ubuntu16下的redis沒有protected-mode屬性&#xff0c;就算sudo啟動&#xff0c;也不能往/var/spool/cron/crontabs寫計劃任務&#xff0c;感覺很安全 #連接到redis redis-cli -h 127.0.0.1 -p 6379 …

Docker核心概念

容器介紹 Docker 是世界領先的軟件容器平臺&#xff0c;所以想要搞懂 Docker 的概念我們必須先從容器開始說起。 什么是容器? 先來看看容器較為官方的解釋 一句話概括容器&#xff1a;容器就是將軟件打包成標準化單元&#xff0c;以用于開發、交付和部署。 容器鏡像是輕量…

阿里云可觀測全面擁抱 OpenTelemetry 社區

作者&#xff1a;古琦 在云計算、微服務、容器化等技術重塑 IT 架構的今天&#xff0c;系統復雜度呈指數級增長。在此背景下&#xff0c;開源可觀測性技術已從輔助工具演變為現代 IT 系統的"數字神經系統"&#xff0c;為企業提供故障預警、性能優化和成本治理的全方…

2025年2月科技熱點深度解析:AI競賽、量子突破與開源革命

引言 2025年的科技領域持續呈現爆發式增長&#xff0c;AI大模型競爭白熱化、量子計算商業化加速、開源工具生態繁榮成為本月最受關注的議題。本文結合最新行業動態&#xff0c;從技術突破、商業布局到開發者生態&#xff0c;全面解析當前科技熱點&#xff0c;為讀者提供深度洞…

idea創建第一個springboot程序

說明&#xff1a; 我計劃用idea&#xff0c;創建第一個springboot程序&#xff0c;但是作為新手完全不會弄&#xff0c;今天我就親自嘗試一邊&#xff0c;并且出一期詳細&#xff0c;完美的教程&#xff0c;親測可以運行 step1. 點擊file &#xff0c; 選new&#xff0c; 選…

半導體芯片制造中 W CVD(鎢化學氣相沉積)

半導體芯片制造中 W CVD&#xff08;鎢化學氣相沉積&#xff09; 的 Nucleation 解析 在鎢&#xff08;W&#xff09;化學氣相沉積&#xff08;CVD&#xff09;工藝中&#xff0c;Nucleation&#xff08;成核&#xff09; 是沉積過程的初始階段&#xff0c;指鎢原子或分子在基…

Three.js 入門(輔助、位移、父子關系、縮放旋轉、響應式布局)

本篇主要學習內容 : 三維坐標系與輔助坐標系物體位移與父子元素物體的縮放與物體的旋轉設置響應式畫布與全屏控制 點贊 關注 收藏 學會了 本文使用 Three.js 的版本&#xff1a;171 基于 Vue3vite開發調試 1.三維坐標系與輔助坐標系 1.1) 導入three和軌道控制器 // 導入…

一鍵導出數據庫表到Excel

工作中&#xff0c;我們經常需要將數據庫表導出到Excel&#xff0c;通常我們會用數據庫編輯器之類的工具提供的導出功能來導出&#xff0c;但是它們的導出功能通常都比較簡單。 這篇文章將介紹一種簡單易用并且功能強大的導出方法。 新增導出 打開的盧導表工具&#xff0c;新…

CSS滾動條原理與自定義樣式指南,CSS滾動條樣式失效,滾動條樣式無效,-webkit-scrollbar無效,overflow不顯示滾動條

滾動內容形成的必要條件 CSS Overflow屬性解析 MDN官方文檔-Overflow屬性 菜鳥教程-Overflow屬性 overflow 屬性控制內容溢出元素框時在對應的元素區間內是否添加滾動條。 值描述visible默認值。內容不會被修剪&#xff0c;會呈現在元素框之外。hidden內容會被修剪&#xf…

【LLM】本地部署LLM大語言模型+可視化交互聊天,附常見本地部署硬件要求(以Ollama+OpenWebUI部署DeepSeekR1為例)

【LLM】本地部署LLM大語言模型可視化交互聊天&#xff0c;附常見本地部署硬件要求&#xff08;以OllamaOpenWebUI部署DeepSeekR1為例&#xff09; 文章目錄 1、本地部署LLM&#xff08;以Ollama為例&#xff09;2、本地LLM交互界面&#xff08;以OpenWebUI為例&#xff09;3、本…