0904 類的繼承

Part 1.梳理思維導圖

一.繼承中的特殊成員函數

1.構造函數

父類的構造函數會被繼承到子類中,在構造的順序中,是先構造父類,再構造子類

#include <iostream>using namespace std;class Father
{
public:string name;
protected:int *age;
private:int weight;
public:Father(){age = nullptr;cout << "Father::無參構造函數" << endl;}Father(string n,int a,int w):name(n),age(new int(a)),weight(w){cout << "Father::有參構造函數" << endl;}void show(){cout << name << " " << *age << " " << weight << endl;}
};class Son:public Father
{
private:string sonname;int *sonage;
public:Son(){sonage = nullptr;cout << "Son::無參構造函數" << endl;}Son(string sn,int sa,string fn,int a,int w):Father(fn,a,w),sonname(sn),sonage(new int(sa)){cout << "Son::有參構造函數" << endl;}void show(){cout << sonname << " " << *sonage << " ";Father::show();}
};int main()
{Son s1("張四",18,"張三",40,100);s1.show();return 0;
}

在創建子類時,會先調用父類的構造函數,再調用子類的構造函數

2.析構函數

父類的析構函數會被繼承到子類中,在析構的順序中,先析構子類,再析構父類

#include <iostream>using namespace std;class Father
{
public:string name;
protected:int *age;
private:int weight;
public:Father(){age = nullptr;cout << "Father::無參構造函數" << endl;}Father(string n,int a,int w):name(n),age(new int(a)),weight(w){cout << "Father::有參構造函數" << endl;}~Father(){delete age;age = nullptr;cout << "Father::析構函數" << endl;}void show(){cout << name << " " << *age << " " << weight << endl;}
};class Son:public Father
{
private:string sonname;int *sonage;
public:Son(){sonage = nullptr;cout << "Son::無參構造函數" << endl;}Son(string sn,int sa,string fn,int a,int w):Father(fn,a,w),sonname(sn),sonage(new int(sa)){cout << "Son::有參構造函數" << endl;}~Son(){delete sonage;sonage = nullptr;cout << "Son::析構函數" << endl;}void show(){cout << sonname << " " << *sonage << " ";Father::show();}
};int main()
{Son s1("張四",18,"張三",40,100);s1.show();return 0;
}

在函數結束時,釋放子類,會先調用子類的析構函數,再調用父類的析構函數

3.拷貝構造函數

父類的拷貝構造函數函數會被繼承到子類中,如果有深拷貝的問題,子類父類完成各自的拷貝工作

#include <iostream>using namespace std;class Father
{
public:string name;
protected:int *age;
private:int weight;
public:Father(){age = nullptr;cout << "Father::無參構造函數" << endl;}Father(string n,int a,int w):name(n),age(new int(a)),weight(w){cout << "Father::有參構造函數" << endl;}~Father(){delete age;age = nullptr;cout << "Father::析構函數" << endl;}Father(const Father &other):name(other.name),age(new int(*(other.age))),weight(other.weight){cout << "Father::拷貝構造函數" << endl;}void show(){cout << name << " " << *age << " " << weight << endl;}
};class Son:public Father
{
private:string sonname;int *sonage;
public:Son(){sonage = nullptr;cout << "Son::無參構造函數" << endl;}Son(string sn,int sa,string fn,int a,int w):Father(fn,a,w),sonname(sn),sonage(new int(sa)){cout << "Son::有參構造函數" << endl;}~Son(){delete sonage;sonage = nullptr;cout << "Son::析構函數" << endl;}Son(const Son &other):Father(other),sonname(other.sonname),sonage(new int(*(other.sonage))){cout << "Son::拷貝構造函數" << endl;}void show(){cout << sonname << " " << *sonage << " ";Father::show();}
};int main()
{Son s1("張四",18,"張三",40,100);s1.show();Son s2 = s1;s2.show();return 0;
}

在子類對象就行拷貝構造時,會調用子類的拷貝構造函數拷貝子類的內容,并調用父類的拷貝構造函數拷貝父類內容,最后構造另一個子類對象

4.拷貝賦值函數

父類的拷貝賦值函數函數會被繼承到子類中,如果有深拷貝的問題,子類父類完成各自的拷貝工作

#include <iostream>using namespace std;class Father
{
public:string name;
protected:int *age;
private:int weight;
public:Father(){age = nullptr;cout << "Father::無參構造函數" << endl;}Father(string n,int a,int w):name(n),age(new int(a)),weight(w){cout << "Father::有參構造函數" << endl;}Father &operator=(const Father &other){if(this != &other){name = other.name;age = new int(*(other.age));weight = other.weight;}cout << "Father::拷貝賦值函數" << endl;return *this;}void show(){cout << name << " " << *age << " " << weight << endl;}
};class Son:public Father
{
private:string sonname;int *sonage;
public:Son(){sonage = nullptr;cout << "Son::無參構造函數" << endl;}Son(string sn,int sa,string fn,int a,int w):Father(fn,a,w),sonname(sn),sonage(new int(sa)){cout << "Son::有參構造函數" << endl;}Son &operator=(const Son &other){if(this != &other){sonname = other.sonname;sonage = new int(*(other.sonage));Father::operator = (other);}cout << "Son::拷貝賦值函數" << endl;return *this;}void show(){cout << sonname << " " << *sonage << " ";Father::show();}
};int main()
{Son s1("張四",18,"張三",40,100);s1.show();Son s3;s3 = s1;s3.show();return 0;
}

二.多繼承

1.概念

一個子類繼承了多個父類

2.格式

class 類名: 繼承方式1 類名1,繼承方式2 類名2,...,繼承方式n 類名n
{子類的拓展;
};

3.例子

#include <iostream>using namespace std;class Sofa
{
private:string sit;
public:Sofa(){cout << "Sofa::無參構造函數" << endl;}Sofa(string sit):sit(sit){cout << "Sofa::有參構造函數" << endl;}~Sofa(){cout << "Sofa::析構函數" << endl;}void show(){Jiaju::show();cout << sit << endl;}
};class Bed
{
private:string sleep;
public:Bed(){cout << "Bed::無參構造函數" << endl;}Bed(string sleep):sleep(sleep){cout << "Bed::有參構造函數" << endl;}~Bed(){cout << "Bed::析構函數" << endl;}void show(){Jiaju::show();cout << sleep << endl;}
};class Bedsofa:public Sofa,public Bed
{
private:string color;
public:Bedsofa(){cout << "Bedsofa::無參構造函數" << endl;}Bedsofa(string sit,string sleep,string color,):Sofa(sit),Bed(sleep),color(color){cout << "Bedsofa::有參構造函數" << endl;}~Bedsofa(){cout << "Bedsofa::析構函數" << endl;}void show(){Bed::show();Sofa::show();cout << color << endl;}
};int main()
{Bedsofa b1("能坐","能躺","白色",100);b1.show();return 0;
}

4.小結

多繼承可以使一個子類擁有多個父類的數據成員與成員函數,由于是多個父類,所以再構造子類對象時,會先構建父類;

在子類的構造函數中,注意調用父類的順序,該順序就是在子類頭部聲明調用父類的順序

三.菱形繼承

1.概念

一個公共基類生出多個中間子類,這些中間子類生出一個匯聚子類,這就是菱形繼承

(一個父類生出多個子類,這些子類合出一個孫類)

2.例子

#include <iostream>using namespace std;
class Jiaju
{
private:int weight;
public:Jiaju(){cout << "Jiaju::無參構造函數" << endl;}Jiaju(int weight):weight(weight){cout << "Jiaju::有參構造函數" << endl;}~Jiaju(){cout << "Jiaju::析構函數" << endl;}void show(){cout << weight << endl;}
};class Sofa:public Jiaju
{
private:string sit;
public:Sofa(){cout << "Sofa::無參構造函數" << endl;}Sofa(string sit,int weight):Jiaju(weight),sit(sit){cout << "Sofa::有參構造函數" << endl;}~Sofa(){cout << "Sofa::析構函數" << endl;}void show(){Jiaju::show();cout << sit << endl;}
};class Bed:public Jiaju
{
private:string sleep;
public:Bed(){cout << "Bed::無參構造函數" << endl;}Bed(string sleep,int weight):Jiaju(weight),sleep(sleep){cout << "Bed::有參構造函數" << endl;}~Bed(){cout << "Bed::析構函數" << endl;}void show(){Jiaju::show();cout << sleep << endl;}
};class Bedsofa:public Sofa,public Bed
{
private:string color;
public:Bedsofa(){cout << "Bedsofa::無參構造函數" << endl;}Bedsofa(string sit,string sleep,string color,int weight):Sofa(sit,weight),Bed(sleep,weight),color(color){cout << "Bedsofa::有參構造函數" << endl;}~Bedsofa(){cout << "Bedsofa::析構函數" << endl;}void show(){Bed::show();Sofa::show();cout << color << endl;}
};int main()
{Bedsofa b1("能坐","能躺","白色",100);b1.show();return 0;
}

在該函數中,公共基類(jiaju)生出兩個中間子類(bed和sofa),最后倆中間子類生出一個匯聚子類(bedsofa),匯聚子類用到了多繼承,繼承兩個父類及兩個中間子類,倆中間子類的共同父類及公共基類

3.菱形繼承的弊端及分析

????????A.弊端

1.匯聚子類會得到多分由中間子類繼承下來的公共基類,這樣會浪費空間

2.匯聚子類對象創建時,會多次調用公共基類的構造函數和析構函數

? ? ? ? B.原因

1.因為子類創建時都會調用父類,在匯聚子類創建時,會調用自己的父類及中間子類,bedsofa創建類對象按順序會調用sofa和bed的構造函數,但是sofa和bed會先調用自己父類及公共基類的構造函數,按調用順序是:jiaju - sofa - jiaju - bed - bedsofa,所以在構造和析構時,jiaju的構造函數和析構函數都會被多次調用。如果函數中有指針類型成員,在析構時會多次delete空間,會出現錯誤

2.按上述所講,子類會繼承父類所有數據成員和成員函數,有兩個中間子類,匯聚子類就會繼承到兩次公共基類

四.虛繼承

1.作用

解決菱形繼承的錯誤,讓多個中間子類只繼承一次公共基類

2.格式

在中間子類繼承前面加上virtual

class 類名:virtual 繼承方式 類名  // 中間子類
{中間子類分拓展;
};

3.注意事項

1.由于中間子類中的公共基類太多,編譯器不清楚應該保存公共基類哪些成員函數,所以會直接保存公共基類的無參構造函數,所以如果需要公共基類的有參構造函數,需要在匯集子類里手動調用

2.所有虛繼承的中間子類會返回一個公共基類,如果有中間子類沒有虛繼承,那個中間子類會返回公共基類,所以需要把所有中間子類都虛繼承

4.示例

#include <iostream>using namespace std;
class Jiaju
{
private:int weight;
public:Jiaju(){cout << "Jiaju::無參構造函數" << endl;}Jiaju(int weight):weight(weight){cout << "Jiaju::有參構造函數" << endl;}~Jiaju(){cout << "Jiaju::析構函數" << endl;}void show(){cout << weight << endl;}
};class Sofa:virtual public Jiaju//虛繼承
{
private:string sit;
public:Sofa(){cout << "Sofa::無參構造函數" << endl;}Sofa(string sit,int weight):Jiaju(weight),sit(sit){cout << "Sofa::有參構造函數" << endl;}~Sofa(){cout << "Sofa::析構函數" << endl;}void show(){Jiaju::show();cout << sit << endl;}
};class Bed:virtual public Jiaju//虛繼承
{
private:string sleep;
public:Bed(){cout << "Bed::無參構造函數" << endl;}Bed(string sleep,int weight):Jiaju(weight),sleep(sleep){cout << "Bed::有參構造函數" << endl;}~Bed(){cout << "Bed::析構函數" << endl;}void show(){Jiaju::show();cout << sleep << endl;}
};class Bedsofa:public Sofa,public Bed
{
private:string color;
public:Bedsofa(){cout << "Bedsofa::無參構造函數" << endl;}Bedsofa(string sit,string sleep,string color,int weight):Jiaju(weight),Sofa(sit,weight),Bed(sleep,weight),color(color)//匯聚子類手動調用公共基類{cout << "Bedsofa::有參構造函數" << endl;}~Bedsofa(){cout << "Bedsofa::析構函數" << endl;}void show(){Bed::show();Sofa::show();cout << color << endl;}
};int main()
{Bedsofa b1("能坐","能躺","白色",100);b1.show();return 0;
}

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

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

相關文章

PDF教程|如何把想要的網頁保存下來?

前段時間有個小伙伴咨詢了小白&#xff1a;領導想要某個網頁的整個頁面&#xff0c;有沒有比較好的方法把它保存下來&#xff1f; 在他找到小白之前&#xff0c;這種事情他已經接到好幾次了&#xff0c;每次都是怎么解決的呢&#xff1f;其實很簡單&#xff0c;就是打開Word&a…

【bash】命令查看當前目錄下文件個數

要用 ls 查看當前目錄下的文件個數&#xff0c;可以結合 wc -l 來統計行數&#xff1a; ls -1 | wc -l說明&#xff1a; ls -1&#xff1a;以一行一個文件的方式列出。wc -l&#xff1a;統計行數&#xff0c;也就是文件/目錄的數量。 ?? 需要注意&#xff1a; 這個方法會把文…

「日拱一碼」081 機器學習——梯度增強特征選擇GBFS

目錄 什么是梯度增強特征選擇&#xff08;GBFS&#xff09; 為什么 GBM 適合做特征選擇 GBFS 的一般步驟 代碼示例 什么是梯度增強特征選擇&#xff08;GBFS&#xff09; GBFS 并非一個像 Lasso 或隨機森林那樣有嚴格標準定義的獨立算法&#xff0c;而是一種基于梯度提升機…

解構匯編, 萬物起源

匯編的誕生匯編全景圖核心主干: CPU架構主要分支: 語法和工具共同的地貌: 核心概念延伸: 跨平臺 & 跨架構跨平臺跨架構總結以 GAS vs. NASM 為例NASM 不支持跨架構 ≠ 無法在ARM架構上的系統安裝匯編的誕生 機器語言的困境 早期的程序員直接使用機器語言進行編程機器語言由…

廣州旅游網站系統 - 純靜態旅游展示平臺

&#x1f31f; 廣州旅游網站系統 - 純靜態旅游展示平臺觀世界才有世界觀 - 一個集景區展示、旅游攻略、文化傳播于一體的精美旅游網站&#x1f4cb; 項目概述 這是一個專注于廣州旅游文化的純靜態網站系統&#xff0c;采用現代化的前端技術棧&#xff0c;為游客提供全方位的廣州…

Qt UDP通信學習

Qt UDP通信學習 一、項目概述 本項目基于Qt框架實現了UDP通信功能&#xff0c;支持單播與廣播消息收發&#xff0c;展示了UDP套接字的基本用法&#xff0c;適合初學者學習Qt網絡模塊的實際應用。 二、項目結構 55.pro&#xff1a;Qt工程文件&#xff0c;配置模塊與源碼文件main…

古德哈特定律(Goodhart‘s Law)

古德哈特定律&#xff08;Goodhart’s Law&#xff09;表述為“當一個指標變成了目標&#xff0c;它將不再是個好指標”。 該定律由英國經濟學家查爾斯古德哈特&#xff08;Charles Goodhart&#xff09;在1975年提出&#xff0c;最初用于批判撒切爾夫人政府的貨幣主義政策&…

在 ASP.NET Core 8 Web API 中實現基于角色的授權 安全且可擴展 API 的最佳實踐

掌握基于角色的授權&#xff1a;使用專家策略保護您的 ASP.NET Core 8 Web API。在 ASP.NET Core 8 Web API 中實現基于角色的授權&#xff1a;安全且可擴展 API 的最佳實踐介紹授權是任何 Web 應用程序的關鍵組件。在開發 API 時&#xff0c;使用基于角色的授權保護端點可確保…

AutoHotkey識別圖片

一、下載ImagePut插件 下載地址&#xff1a;GitHub - iseahound/ImagePut: A core library for images in AutoHotkey. Supports AutoHotkey v1 and v2. 二、將插件和要搜索的圖片導入項目 #Include ./plugin/ImagePut.ahk ; 截取當前屏幕 pic : ImagePutBuffer(0) point : p…

CamX-Camera常用編譯命令和adb指南

g_camxsettings vendor/qcom/proprietary/camx/src/settings/g_camxsettings.xml 控制相機debug的信息都在該文件里面 0、相關代碼 framwork層 frameworks/av/camera/ frameworks/av/services/camera frameworks/av/services/camera frameworks/hardware/interfaces/camerase…

LabVIEW 實現顏色平滑漸變控制

LabVIEW 中實現 LED 顏色從藍到紅的平滑漸變顯示在 LabVIEW 開發中&#xff0c;若需讓 LED&#xff08;或類 LED 顯示控件&#xff09;實現從藍色到紅色的平滑色彩漸變&#xff08;模擬溫度等參數從低到高的視覺反饋&#xff09;&#xff0c;可通過自定義顏色查找表 數值縮放映…

陰陽學:從入門到精通

第一篇&#xff1a;入門篇——陰陽基礎理論1.1 陰陽的起源與哲學意義陰陽概念的歷史淵源《易經》中的陰陽思想陰陽與宇宙、自然、人生的關系陰陽對思想、行為、社會的影響1.2 陰陽的基本屬性與符號陰陽的特征、象征與對立統一陰陽在自然界的表現&#xff08;晝夜、冷熱、動靜等…

Java工業通信實戰(三):Modbus RTU串口通信實現

想象一下&#xff0c;你要和一臺工業設備"對話"&#xff0c;比如詢問溫度傳感器"現在多少度&#xff1f;“或者告訴電機"轉快一點”。 Modbus RTU就是這種"對話"的標準語言&#xff0c;就像人與人之間說普通話一樣。 它采用主從結構&#xff0c;…

CentOS安裝或升級protoc

卸載舊版本 sudo yum remove protobuf protobuf-c protobuf-compiler -y sudo rm -f /usr/bin/protoc sudo rm -rf /usr/include/google/protobuf 下載 wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.0/protoc-3.15.0-linux-x86_64.zip unz…

人工智能在醫學圖像中的應用:從機器學習到深度學習

目的&#xff1a;人工智能&#xff08;AI&#xff09;模型在生物醫學研究和醫療服務中扮演著越來越重要的角色。本綜述聚焦于在現實世界背景下&#xff0c;開發AI應用作為臨床決策支持系統時需要澄清的挑戰性問題。方法&#xff1a;進行了一項敘述性綜述&#xff0c;包含對1989…

基于Echarts+HTML5可視化數據大屏展示-智慧小區大數據分析

效果展示&#xff1a;代碼結構&#xff1a;主要代碼實現 index.html布局 <!doctype html> <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8"><title>智慧農業大數據展示</title><link rel"s…

【LeetCode熱題100道筆記】驗證二叉搜索樹

題目描述 給你一個二叉樹的根節點 root &#xff0c;判斷其是否是一個有效的二叉搜索樹。 有效 二叉搜索樹定義如下&#xff1a; 節點的左子樹只包含 嚴格小于 當前節點的數。 節點的右子樹只包含 嚴格大于 當前節點的數。 所有左子樹和右子樹自身必須也是二叉搜索樹。 示例 1&…

Apache Tomcat 教程:從入門到精通(含目錄結構與版本詳解)

??????1. 背景?? Apache Tomcat 是一個開源的 ??Java Servlet 容器??&#xff0c;由 ??Apache 軟件基金會&#xff08;ASF&#xff09;?? 開發和維護&#xff0c;最初由 ??Sun Microsystems?? 的軟件架構師 ??James Duncan Davidson?? 設計&#xff0…

設計模式從入門到精通之(六)策略模式

策略模式&#xff1a;讓算法靈活切換的秘密武器在日常開發中&#xff0c;算法的選擇常常是程序設計的核心&#xff0c;比如支付方式的選擇、排序邏輯的切換、促銷活動的動態調整等。當需求變化時&#xff0c;我們需要在多個算法之間切換&#xff0c;但又不希望修改已有代碼。如…

安裝MATLAB205軟件記錄

安裝MATLAB2025 一臺電腦可以安裝多個版本的MATLAB; 下載資源 微信公眾平臺-MATLAB R2025a v25.1下載及安裝教程 安裝步驟 解壓, 壓縮文件大小為13.8GB 裝載 選中setup.exe右鍵單擊以管理員身份運行 我有文件安裝密鑰 接受許可條款 復制粘貼密鑰 63733-59078-50866-02827-…