《C++ 繼承》

目錄

繼承的定義

繼承類模板

派生類和基類之前的轉換

隱藏

派生類的默認成員函數

不能被繼承的類

繼承中的友元和靜態成員

繼承模型


繼承的定義

繼承的本質是一種復用。規定Person類為基類,Student類為派生類 。

繼承方式分為public繼承protected繼承private繼承。一般使用public繼承,對成員的限制private > protected > public.

public繼承,基類的private成員只能在基類使用,protected成員只能在基類和派生類中使用,public成員能在任意地方使用。

protect繼承,基類的private成員只能在基類使用,protected成員只能在基類和派生類中使用,public成員只能在基類和派生類中使用。

private繼承,基類的private成員只能在基類使用,protected成員只能在基類中使用,public成員只能在基類中使用。

//基類/父類
class Person
{
public://身份認證void identity(){cout << "void identity()" << endl;}void func(){_age++;}protected:string _name = "張三";string _address;string _tel;
private:int _age = 18;
};//子類/派生類
class Student : public Person
{
public://學習void study(){cout << "void study()" << endl;}//不能在派生類聲明時直接在派生類中來改變基類的成員變量//_name = "李四";void Set_name(){_name = "李四";}
protected:int _stuid;//學號
};//不顯示寫繼承方式 默認為private繼承
//class Teacher : Person
class Teacher : public Person
{
public:void teach(){cout << "void teach()" << endl;//派生類中無法訪問基類的private成員//age++;}protected:int _work_num;//工號};int main()
{Person p;p.identity();//基類調用成員函數Student s;s.identity();//派生類調用基類的成員函數Teacher t;t.identity();s.func();//調用基類的函數來改變基類的private變量s.Set_name();//調用成員函數可以該改變基類中的potected變量return 0;
}

繼承類模板

在復用容器中的函數時會報錯找不到標識符push_back()。

因為lzk::stack<int> s實例化了stack<int>和vector<int>,但是沒有實例化vector<int>::push_back(x)。
這里的問題本質上時編譯器對模板的兩階段查找規則
第一階段(模板定義階段)模板定義時自動觸發(無需實例化)
?? ??? ??? ?編譯器會檢查所有不依賴模板參數 T 的名稱(即非依賴名稱,如直接寫的 push_back)。
?? ??? ??? ?如果名稱未在當前作用域或可見基類中聲明,直接報錯(即使基類模板實例化后可能有該成員)。

第二階段(模板實例化階段)實例化模板時觸發(如 main() 中使用)
?? ??? ??? ?檢查所有依賴 T 的名稱(如 vector<T>::push_back)。
?? ??? ??? ?此時基類模板(如 vector<int>)已實例化,可以確認成員是否存在。

//基類為類模板
namespace lzk
{template<class T>class stack : public vector<T>{public:void push(const T& x){//報錯找不到標識符//push_back();//lzk::stack<int> s;時實例化了stack<int> 和vector<int>//但是沒有實例化vector<int>::push_back(x)//這里的問題本質上時編譯器對模板的兩階段查找規則/*第一階段(模板定義階段)編譯器會檢查所有不依賴模板參數 T 的名稱(即非依賴名稱,如直接寫的 push_back)。如果名稱未在當前作用域或可見基類中聲明,直接報錯(即使基類模板實例化后可能有該成員)。這就是你遇到的 push_back 報錯的根本原因。第二階段(模板實例化階段)檢查所有依賴 T 的名稱(如 vector<T>::push_back)。此時基類模板(如 vector<int>)已實例化,可以確認成員是否存在。*///階段1:模板定義時自動觸發(無需實例化)。//階段2:實例化模板時觸發(如 main() 中使用)。vector<int>::push_back(x);}void pop(){vector<int>::pop_back();}const T& top(){return vector<int>::back();}bool empty(){return vector<int>::empty();}};}int main()
{lzk::stack<int> s;s.push_back(1);s.push_back(2);s.push_back(3);s.push_back(4);while (!s.empty()){cout << s.top() << endl;s.pop();}return 0;
}

派生類和基類之前的轉換

public繼承的派生類對象可以賦值給基類的對象和指針和引用,但是基類對象不能賦值給派生類對象。?

//派生類對象和基類對象的轉換
class Person
{
protected:string _name;string _sex;int _age;
};class Student : public Person
{
public:int _num;
};int main()
{Student s;//派生類對象可以賦值給基類的指針引用Person* p = &s;Person& rp = s;//派生類對象賦值給基類對象,通過基類的拷貝構造完成Person pojb = s;return 0;
}

隱藏

我們知道不同的類,有不同的類域,他們是相互獨立的,如果基類和派生類中存在同名成員變量或同名成員函數,派生類成員將屏蔽基類對同名成員的直接訪問,即隱藏。?

class Person
{
protected:string _name = "李四";string _sex = "男";int _age = 18;
public:void func(){cout << "func()" << endl;}
};class Student : public Person
{
public:void print(){//將基類中的_age隱藏了cout << _age << endl;}int _num = 22;int _age = 19;void func(int i){cout << "void func(int i)" << endl;}
};int main()
{Student s;s.print();//通過派生類對象調用基類隱藏函數,需要指定類域s.func(1);s.Person::func();return 0;
}

派生類的默認成員函數

構造函數的調用順序是,先調用基類的構造函數,再調用派生類的構造函數;先析構派生類對象,再析構基類對象。?

如果顯示調用基類的析構,有兩個問題

1.在編譯過后,編譯器會將基類和派生類的析構函數名稱改為destructor,那么基類和派生類的析構函數就會構成隱藏關系,則需要指定類域調用
2.調用過后發現基類析構了兩次,編譯器為了析構的順序是先派生類再基類,會在調用派生類的析構后再調用基類析構,如果有動態資源就會報錯。

//派生類的默認成員函數//基類
class Person
{
public:Person(const string& name = "張三"):_name(name){cout << "Person(const string& name = 張三)" << endl;}Person(const Person& p):_name(p._name){cout << "Person(const Person& p)" << endl;}Person& operator=(const Person& p){cout << "Person& operator=(const Person& p)" << endl;if (this != &p){_name = p._name;}return *this;}~Person(){cout << "~Person()" << endl;_name = "";}
protected:string _name;};//派生類
class Student : public Person
{
public:Student(const string& n, int age, const string& name):Person(name), _n(n), _age(age){cout << "Student(const string& n, int age, const string& name)" << endl;}Student(const Student& s):Person(s)//顯示調用基類的拷貝構造,_n(s._n),_age(s._age){cout << "Student(const Student& s)" << endl;}Student& operator=(const Student& s){cout << "Student& operator=(const Student& s)" << endl;if (this != &s){_n = s._n;_age = s._age;Person::operator=(s);//顯示調用基類的賦值重載}return *this;}~Student(){//如果顯示調用基類的析構,有兩個問題//1.//在編譯過后,編譯器會將基類和派生類的析構函數名稱改為destructor(涉及到多態)//那么基類和派生類的析構函數就會構成隱藏關系//則需要指定類域調用//2.//調用過后發現基類析構了兩次//編譯器為了析構的順序是先派生類再基類 //會在調用派生類的析構后再調用基類析構    //如果有動態資源就會報錯//Person::~Person();cout << "~student()" << endl;}
private:string _n = "李四";int _age = 19;};int main()
{Student s("李好", 19,"張斌");Student s1(s);//Student s3("李一", 18,"李二" );//s1 = s3;return 0;
}

不能被繼承的類

實現一個不能被繼承的類有兩種方法

一是將基類的構造函數列為私有成員。

二是在基類的名字后面加final關鍵字。

//實現一個不能被繼承的類
//c++11
class Base final//加關鍵字
{
public:	 void func5() { cout << "Base::func5" << endl; }
protected:int a = 1;
private://c++98 //將構造函數設為私有//Base()//{};
};
//報錯
//class Student : public Base

繼承中的友元和靜態成員

友元關系不能被繼承,基類的友元函數不能訪問派生類的成員變量,除非給派生類也聲明友元。

在基類中定義了靜態成員,則在派生類中使用的也是這個成員,不會再開辟新的空間。

//繼承和友元//前置聲明
class Student;class Person
{
public:friend void print(const Person& p, const Student& s);
protected:int _age = 18;
};class Student : public Person
{
protected:string _name = "李思思";friend void print(const Person& p, const Student& s);
};void print(const Person& p, const Student& s)
{cout << p._age << endl;cout << s._name << endl;
}int main()
{Student s;Person p;print(p,s);return 0;
}//靜態成員class Person
{
public:string _name;static int _count;
};//靜態成員在類外定義
int Person::_count = 0;class Student : public Person
{
protected:int _stuNum;
};int main()
{Person p;Student s;//基類和派生類公用一個靜態變量cout << &p._count << endl;cout << &s._count << endl;//基類和派生類非靜態成員的地址是不一樣的cout << &p._name << endl;cout << &s._name << endl;//通過指定類域可以訪問靜態成員cout << &Person::_count << endl;cout << &Student::_count << endl;return 0;
}

繼承模型

單繼承:一個派生類繼承一個基類。

多繼承:一個派生類繼承多個基類。

菱形繼承:諸如兩個派生類繼承同一個基類后,再被同一個派生類繼承的情況。

菱形繼承會產生數據冗余二義性的問題,為了解決這個問題就有了虛繼承,虛繼承就是在繼承方式前面加上virtual關鍵字。那么派生類對象就可以訪問基類公開成員了。

//單繼承 多繼承 菱形繼承
class Person
{
public:string _name = "李思思";
};class Student : public Person
{
public:int _nun;
};class Teacher : public Person
{
public:int _worknum;
};class Assistant : public Student, public Teacher
{
protected:string _course; // 主修課程
};int main()
{//對_name的訪問不明確//student類和teacher類中都有_nameAssistant a;//a._name = "lisisi";//指定類域可以訪問,解決二義性問題,但是存在數據冗余a.Student::_name = "lisisi";a.Teacher::_name = "lss";
}//虛繼承
//解決數據冗余和二義性class Person
{
public:string _name = "李思思";
};//加關鍵字virtaul
class Student : virtual public Person
{
public:int _nun;
};class Teacher : virtual public Person
{
public:int _worknum;
};class Assistant : public Student, public Teacher
{
protected:string _course; // 主修課程
};int main()
{Assistant a;a._name = "李思思";return 0;
}

任何足夠先進的科技都與魔法無異,但魔法背后的真相永遠是嚴謹的代碼邏輯。愿我們既能享受創造的浪漫,也能保持對技術的敬畏之心?!🚀

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

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

相關文章

金蝶K3 ERP 跨網段訪問服務器卡頓問題排查和解決方法

我一朋友公司反應&#xff0c;公司網絡卡頓&#xff0c;測試掉包嚴重&#xff0c;抓包wireshark測試&#xff0c;發現arp包有大量mac欺騙&#xff0c;因為公司有幾百臺電腦&#xff0c;所以建議更換了三層交換機&#xff0c;劃分了vlan&#xff0c;這樣有效的避免了網絡風暴等&…

無需安裝!在線數據庫工具 :實戰 SQL 語句經典案例

在數字化時代&#xff0c;SQL&#xff08;結構化查詢語言&#xff09;已成為數據從業者、開發人員乃至業務分析人員必備的核心技能。無論是處理日常數據報表&#xff0c;還是應對復雜的業務邏輯&#xff0c;SQL 都能高效實現數據的查詢、操作與分析。本文將通過經典的 SQL 練習…

如何在網頁里填寫 PDF下拉框

對于PDF 開發者或網頁開發者來說&#xff0c;讓用戶在網站上填寫 PDF 下拉框&#xff08;Combo Box&#xff09;是一個棘手的問題。因為 PDF 并不是一種原生的 Web 格式&#xff0c;瀏覽器通常不允許用戶與 PDF 下拉框進行交互。 那么&#xff0c;如何讓用戶在 HTML 中填寫 PD…

.Net 優秀框架 ABP全面詳解

文章目錄 第一部分&#xff1a;ABP框架概述與核心架構1.1 ABP框架簡介1.2 ABP框架架構解析1.2.1 表現層(Presentation Layer)1.2.2 分布式服務層(Distributed Service Layer)1.2.3 應用層(Application Layer)1.2.4 領域層(Domain Layer)1.2.5 基礎設施層(Infrastructure Layer)…

力扣-198.打家劫舍

題目描述 你是一個專業的小偷&#xff0c;計劃偷竊沿街的房屋。每間房內都藏有一定的現金&#xff0c;影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統&#xff0c;如果兩間相鄰的房屋在同一晚上被小偷闖入&#xff0c;系統會自動報警。 給定一個代表每個房屋…

windows 安裝vllm cuda版本

windows 安裝cuda版本 查看window cuda版本 nvidia-smi vllm 獲取鏡像,此版本需要cuda 版本12.8 或以上 docker pull vllm/vllm-openai:latest下載模型 git lfs installcd e:\ai mkdir vllm\models\qwen2cd vllm\models#通過git下載git clone https://www.modelscope.c…

Node.js特訓專欄-基礎篇:1. Node.js環境搭建與項目初始化詳細指南

我將為你詳細講解 Node.js 環境搭建與項目初始化的步驟&#xff0c;包含常見問題解決和最佳實踐&#xff0c;幫助你快速上手。 詳細步驟說明 1. 環境搭建 Windows用戶&#xff1a; 訪問Node.js官網(https://nodejs.org)下載LTS版本安裝包&#xff08;推薦長期支持版&#xf…

13.安卓逆向2-frida hook技術-HookJava構造方法

免責聲明&#xff1a;內容僅供學習參考&#xff0c;請合法利用知識&#xff0c;禁止進行違法犯罪活動&#xff01; 內容參考于&#xff1a;圖靈Python學院 工具下載&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取碼&#xff1…

php基礎:常見函數

內建函數 文章目錄 內建函數1、文件操作函數&#xff1a;2、代碼執行函數&#xff1a;3、反序列化函數&#xff1a;4、數據庫操作函數&#xff1a;5、類型轉換與比較函數&#xff1a;6、其他常見函數&#xff1a; 1、文件操作函數&#xff1a; include(): 導入并執行指定的 PHP…

教程:PyCharm 中搭建多級隔離的 Poetry 環境(從 Anaconda 到項目專屬.venv)

核心思維&#xff1a;為什么需要 “多級隔離”&#xff1f; 在復雜項目中&#xff0c;環境沖突是最棘手的問題&#xff08;比如系統 Python 版本不同、依賴包版本沖突&#xff09;。通過 “Anaconda 虛擬環境 → 項目 Poetry 環境 → 工具級隔離” 的三層架構&#xff0c;實現…

Rollup vs Webpack 深度對比:前端構建工具終極指南

前端工程領域始終面臨一個根本選擇&#xff1a;如何在模塊化編碼規范與工程化構建效率之間取得最佳平衡。Rollup與Webpack分別代表著兩種不同維度的解決方案&#xff0c;本文將揭示它們的真實應用場景與核心差異。 一、核心差異全景圖&#xff08;附最新對比&#xff09; 核心能…

Module Federation 和 Native Federation 的比較

前言 Module Federation 是 Webpack 5 引入的微前端架構方案&#xff0c;允許不同獨立構建的應用在運行時動態共享模塊。 Native Federation 是 Angular 官方基于 Module Federation 理念實現的專為 Angular 優化的微前端方案。 概念解析 Module Federation (模塊聯邦) Modul…

Easy Excel

Easy Excel 一、依賴引入二、基本使用1. 定義實體類&#xff08;導入/導出共用&#xff09;2. 寫 Excel3. 讀 Excel 三、常用注解說明&#xff08;完整列表&#xff09;四、進階&#xff1a;自定義轉換器&#xff08;Converter&#xff09; 其它自定義轉換器沒生效 Easy Excel在…

iOS 26 攜眾系統重磅更新,但“蘋果智能”仍與國行無緣

美國西海岸的夏天&#xff0c;再次被蘋果點燃。一年一度的全球開發者大會 WWDC25 如期而至&#xff0c;這不僅是開發者的盛宴&#xff0c;更是全球數億蘋果用戶翹首以盼的科技春晚。今年&#xff0c;蘋果依舊為我們帶來了全家桶式的系統更新&#xff0c;包括 iOS 26、iPadOS 26…

AI高考志愿助手應用架構設計并上線實施運行

環境: AI高考志愿助手 問題描述: AI高考志愿助手應用架構設計并上線實施運行 業務需求:開發一個AI升學助手,功能是幫助用戶模擬填報高考志愿等功能,數據是歷年各專業的錄取分數線表格。數據確認: 近3年約100多萬條數據,原始數據是excel表格數據。解決方案: 一、項…

深入淺出掌握 Axios(持續更新)

在了解ajax和axios之前&#xff0c;我們先觀察一下他們是什么英文的縮寫 ajax 的名字為 asynchroanous JavaScript and XML 而axios的名稱來源于英文單詞“axis”與“I/O”的結合&#xff0c;并非直接縮寫自某個特定短語。 先導知識 在本文我們簡單的介紹一下ajax后著重講解…

windows10下搭建nfs服務器

windows10下搭建nfs服務器 有參考這篇博客 Windows10搭建NFS服務 - fuzidage - 博客園 下載 NFS Server這個app 通過網盤分享的文件&#xff1a;nfs1268 (1).exe 鏈接: https://pan.baidu.com/s/1rE4h710Uh-13kWGXvjkZzw 提取碼: mwa4 --來自百度網盤超級會員v5的分享 下載后…

npm符號鏈接

前言 最近在寫一個快應用項目&#xff0c;demo中依賴了本地文件&#xff0c;package.json如下&#xff1a; 此時 node_modules 下出現了 mysdk&#xff0c;復制整個項目&#xff0c;但是copy的項目中的node_modules并未出現該文件&#xff0c;導致報錯。 解決方案 觀察 pa…

SQL 中 IDENTITY 列的特殊處理.

SQL 處理中,遇到提示: "消息 544,級別 16,狀態 1,第 3 行 當 IDENTITY_INSERT 設置為 OFF 時,不能為表 BM 中的標識列插入顯式值。" 即當 SQL Server 表中的 ??標識列(Identity Column)?? 插入顯式值,但未啟用 IDENTITY_INSERT 選項。由此報錯,以下是詳…

網絡安全等級保護中關于SSL證書的整改如何處理?

SSL證書在網絡安全等級保護&#xff08;等保&#xff09;體系中扮演著至關重要的角色&#xff0c;是實現多個等保核心要求&#xff08;尤其是三級及以上&#xff09;的關鍵技術手段之一。其重要性主要體現在以下幾個方面&#xff1a; 滿足“身份鑒別”要求&#xff08;等保要求…