日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++(22)--继承和派生

發(fā)布時(shí)間:2023/12/13 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++(22)--继承和派生 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

繼承和派生

  • 1.基本概念
  • 2.實(shí)現(xiàn)公有繼承
  • 3.私有繼承的例子
  • 4. 繼承和組合

《老九學(xué)堂C++課程》《C++ primer》學(xué)習(xí)筆記。《老九學(xué)堂C++課程》詳情請到B站搜索《老九零基礎(chǔ)學(xué)編程C++入門》
-------------簡單的事情重復(fù)做,重復(fù)的事情用心做,用心的事情堅(jiān)持做(老九君)---------------

1.基本概念

面向?qū)ο髈op–三大重要特性-- 封裝、繼承、多態(tài)

在C++中,代碼重用是通過“繼承(inheritance)”機(jī)制實(shí)現(xiàn)的。
在一個(gè)已經(jīng)存在的類的基礎(chǔ)上,再建立一個(gè)新類。
從已有的類中派生出新類,派生類就繼承了原有類(基類)的特征,包括成員和方法(以后函數(shù)就叫方法)

通過繼承可以完成的功能-可升級(jí)可維護(hù)

  • 在已有類的基礎(chǔ)上增加新的功能,對(duì)于數(shù)組類,可以添加數(shù)學(xué)計(jì)算–排序
  • 給類添加數(shù)據(jù)成員,對(duì)于字符串類,可以派生類,并添加制定成員表示顏色。
  • 修改類的方法,對(duì)于普通英雄,可以派生出擁有更豐富的技能的近戰(zhàn)英雄類
  • 注意:
    繼承機(jī)制只需要提供新的特性,甚至不需要訪問源碼就可以派生出類
    允許在不公開的情況下將自己的類分發(fā)給他人,同時(shí)允許他們在類中添加新的特性。

    程序升級(jí)和擴(kuò)展–非常忌諱的是,修改原有的代碼。原來的代碼測試通過了,測試實(shí)際是一件非常困難的事。

    開發(fā)一款RPG(Role-playing Gam)游戲
    游戲職業(yè):坦克,戰(zhàn)士,刺客,法師,射手,輔助

    1.0 版本:戰(zhàn)士,法師
    直接定義英雄類:戰(zhàn)士類,法師類–存在相同屬性和方法。
    把相同的成員和方法封裝成基類。

    注意:
    1.派生類對(duì)象存儲(chǔ)了基類的數(shù)據(jù)成員
    2.派生類對(duì)象可以調(diào)用基類的非私有函數(shù)
    3.派生類需要自己的構(gòu)造方法
    4.派生類根據(jù)需要增加額外的成員和方法

    繼承的繼承:稱為直接基類和間接基類。

    父類的的成員和方法的公有,私有,和受保護(hù)三種屬性的訪問權(quán)限:
    1.公有權(quán)限下,自己和派生類,以及外部都能訪問
    2.私有權(quán)限下,只有自己訪問,派生類和外部都無法訪問
    3.受保護(hù)權(quán)限下,自己和派生類可以訪問,外部無法訪問
    繼承分為公有繼承,私有繼承,受保護(hù)繼承。三種方式繼承之后子類權(quán)限的變化

    基類成員公有繼承私有繼承保護(hù)繼承
    公有公有私有受保護(hù)
    受保護(hù)受保護(hù)私有受保護(hù)
    私有不被繼承不被繼承不被繼承

    全部繼承,不封裝基類–公有繼承(除了基類的私有成員不繼承,其他都是權(quán)限不變的繼承)is a 關(guān)系。
    全部繼承,完全封裝基類–私有繼承(庶出,除了基類的私有成員不繼承,其他成員繼承后權(quán)限改成私有) has a關(guān)系。使用包含來實(shí)現(xiàn)has a ,用繼承來實(shí)現(xiàn)有點(diǎn)抽象。
    全部繼承,有選擇封裝基類–受保護(hù)(除了基類的私有成員不繼承,其他成員繼承后權(quán)限被改為受保護(hù)模式)

    靈活運(yùn)用面向?qū)ο笏枷氲闹匾w現(xiàn)。
    不管使用哪一種繼承,派生類都不能訪問基類里的私有成員,除非改成protected.

    class Emperor { private:string[] bueaties; // 后宮佳麗double silvers; // 私房錢 protected:string palace; // 宮殿名稱 publicEmperor();~Emperor();string reignTile; // 年號(hào) } // 子類的繼承關(guān)系,非實(shí)際代碼 class FourthSon:public Emperor { // 父類私有成員不可見, protected:string palace; //宮殿名稱 public:FourthSon();~FourthSon();string reignTile; // 年號(hào) } class ThirteenSon:protected Emperor { protected: // 外人訪問不了,只有自己,友元,以及子類能夠訪問。string reignTile; // 年號(hào)string palace; // 宮殿名稱 public:ThirteenSon();~ThirteenSon(); } class SecondSon: private Emperor { private: //僅作說明,只有自己訪問string palace; //宮殿名稱string reignTile; // 年號(hào) piblic:SecondSon();~SecondSon(); }

    2.實(shí)現(xiàn)公有繼承

    掌握公有繼承,了解私有繼承和受保護(hù)繼承。
    滿足is a 關(guān)系的可以用繼承。
    clion 還不會(huì)寫配置文件,類圖生成

    類對(duì)象在內(nèi)存中的存儲(chǔ)情況

  • 在沒有繼承關(guān)系時(shí)的內(nèi)存模型
    a)對(duì)象的成員變量存在堆內(nèi)存區(qū)/棧內(nèi)存區(qū),代碼存儲(chǔ)在公有的成員函數(shù)代碼區(qū)。所有的對(duì)象共同享有一段函數(shù)代碼
    b)如果使用sizeof 求類所占空間的大小,只是計(jì)算了成員變量的大小,并沒有把成員函數(shù)也包含在內(nèi)。
  • 有繼承關(guān)系時(shí)的內(nèi)存模型
    a)派生類的內(nèi)存模型看成是基類成員變量和新增成員變量的總和,所有的成員函數(shù)仍然共有另一個(gè)區(qū)域–代碼區(qū)。
  • 創(chuàng)建的時(shí)候先初始化基類再初始化派生類
    釋放時(shí)先釋放派生類再釋放基類

    demo1: Warrior 公有繼承

    //main.cpp #include <iostream> #include <string> #include "Hero.h" #include "Warrior.h"using namespace std; void HeroTest(); void WarriorTest(); int main() {// HeroTest();WarriorTest(); } void HeroTest() {Hero hero1;cout << hero1 << endl;hero1.Move();Hero * hero2 = new Hero("測試英雄2",999,5000,5000);cout << *hero2 << endl;hero2->Move();//(*hero2).Move(); // 等價(jià)調(diào)用 } void WarriorTest(){Warrior warrior1;// 情況1:派生類中沒有重新實(shí)現(xiàn)move方法,調(diào)用父類方法// 情況2:派生類中重新實(shí)現(xiàn)move方法,調(diào)用子類實(shí)現(xiàn)的該方法warrior1.Move();cout << warrior1 << endl;Hero * hero = new Warrior; // 基類指針指向了派生類--標(biāo)準(zhǔn)的多態(tài)hero->Move(); // 調(diào)用基類的實(shí)現(xiàn)delete hero;} //Hero.h // // Created by 陳瑩瑩 on 2021/3/15. //#ifndef CHAPTER13_1_HERO_H #define CHAPTER13_1_HERO_H#include <string> #include <vector> #include <list> #include <iostream> #include <assert.h> using namespace std; class Hero { private:string m_NickName;int m_Level;int m_MaxLife;int m_CurrLife;int x;int y;public:Hero();Hero(const string& nickName);Hero(const string& nickName, int level);Hero(const string& nickName, int level, int maxLife, int currLife);void Move();friend ostream& operator<<(ostream& out, const Hero& hero);// friend ostream& operator<<(ostream& out, const* hero);string GetNickName() const{return m_NickName;}int GetLevel() const{return m_Level;}int GetMaxLife() const{return m_MaxLife;}int GetCurrLife() const{return m_CurrLife;}void SetNickName(const string & nickName){this->m_NickName = nickName;}void SetLevel(int level);void SetMaxLife(int maxLife);void SetCurrLife(int currLife);void operation1(); }; #endif //CHAPTER13_1_HERO_H //Hero.cpp // // Created by 陳瑩瑩 on 2021/3/15. //#include "Hero.h" #include <string> #include <vector> #include <list> #include <iostream> #include <assert.h> #include "Hero.h" using namespace std;Hero::Hero() : m_NickName("默認(rèn)英雄"),m_Level(1),m_MaxLife(100),m_CurrLife(100) {cout << "調(diào)用了Hero的默認(rèn)構(gòu)造" << endl; } //Hero::Hero(const string& nickName):m_NickName(nickName),m_Level(1),m_MaxLife(100),m_CurrLife(100) //{ // //} Hero::Hero(const string& nickName):Hero(nickName,1,100,10) {cout << "調(diào)用了Hero 一個(gè)參數(shù)版本的構(gòu)造" << endl; } Hero::Hero(const string& nickName, int level):Hero(nickName, level,100,10) {cout << "調(diào)用了Hero 兩個(gè)參數(shù)版本的構(gòu)造" << endl; } Hero::Hero(const string& nickName, int level, int maxLife, int currLife):m_NickName(nickName),m_Level(level),m_MaxLife(maxLife),m_CurrLife(currLife) {cout << "調(diào)用了Hero 四個(gè)參數(shù)版本的構(gòu)造" << endl; } void Hero::Move() {// 默認(rèn)移動(dòng)cout << "普通英雄" << m_NickName << "正在奔跑在艾澤拉斯大陸上" << endl; } ostream& operator<<(ostream& out, const Hero& hero){out << "昵稱:" << hero.GetNickName() << "\n";out << "等級(jí):" << hero.GetLevel() << "\n";out << "最大生命:" << hero.GetMaxLife() << "\n";out << "當(dāng)前生命:" << hero.GetCurrLife() ;return out; } void Hero::operation1() { } //Warrior.h // // Created by 陳瑩瑩 on 2021/3/16. // #ifndef CHAPTER13_1_WARRIOR_H #define CHAPTER13_1_WARRIOR_H #include "Hero.h" // 共有繼承-體現(xiàn)了is a 關(guān)系 class Warrior : public Hero{ private:int m_PhysicalAttack; public:Warrior();Warrior(const string& nickName, int phyAttack);void Move(); // 在派生類中實(shí)現(xiàn)派生類版本的move方法~Warrior(); }; #endif //CHAPTER13_1_WARRIOR_H //Warrior.cpp // // Created by 陳瑩瑩 on 2021/3/16. // #include "Warrior.h" Warrior::Warrior() :Hero("默認(rèn)構(gòu)造",1,100,100) { } Warrior::Warrior(const string& nickName, int phyAttack):Hero(nickName,1,100,100),m_PhysicalAttack(phyAttack) { } void Warrior::Move() {// m_NickName沒辦法過呀,不能訪父類的私有屬性,需要在將父類中私有成員改為受保護(hù)成員//cout << "戰(zhàn)士《" << m_NickName << "》"<< "背著一大堆近戰(zhàn)武器正在前進(jìn)。。。"<< endl;cout << "戰(zhàn)士《" << GetNickName() << "》"<< "背著一大堆近戰(zhàn)武器正在前進(jìn)。。。"<< endl; } Warrior::~Warrior() { }

    有關(guān)基類,派生類構(gòu)造

  • 實(shí)例化派生類對(duì)象時(shí),首先會(huì)創(chuàng)建基類對(duì)象(調(diào)用基類構(gòu)造)
  • 派生類構(gòu)造應(yīng)通過成員初始化列表將基類信息傳遞給基類構(gòu)造
  • 應(yīng)該在派生類構(gòu)造中初始化派生類新增的數(shù)據(jù)成員
  • 派生類與基類之間特殊關(guān)系小結(jié)
    1.派生類可以使用基類的非私有成員函數(shù)(public和protect)

    2.基類指針可以在不進(jìn)行顯示類型轉(zhuǎn)換的情況下指向派生類對(duì)象

    Warrior warrior1("諸葛達(dá)摩", 10, 100, 100); Hero& refHero = warrior1; // 基類引用指向派生類, Hero* ptrHero = &warrior1; // 基類指針指向派生類對(duì)象 Warrior& warrior2 = (Warrior)refHero; // 父類引用/指針需要強(qiáng)制轉(zhuǎn)換成子類引用/指針(前提:父類指針指向子類對(duì)象) //不可以將基類對(duì)象的地址賦給派生類引用和對(duì)象,即不能進(jìn)行逆操作

    3.可以將派生類對(duì)象賦值給基類對(duì)象,程序會(huì)使用隱式重載賦值運(yùn)算符

    Hero hero = warrior; hero.move(); //調(diào)用父類方法

    3.私有繼承的例子

    沒講完呀,暫且收一收好了

    //main.cpp #include <iostream> #include "Teacher.h" void TeacherTest(){Teacher teacher1(8000);// 名字設(shè)置沒有寫完 } int main() {TeacherTest();return 0; } //Teacher.h // // Created by 陳瑩瑩 on 2021/3/21. //#ifndef CHAPTER13_1_TEACHER_H #define CHAPTER13_1_TEACHER_H #include <iostream> #include <string> using namespace std; /** 用來演示私有繼承的其中一種用法* 實(shí)現(xiàn)組合關(guān)系,只能組合一個(gè)屬性不能組合兩個(gè)屬性* Teacher類中擁有string類型的成員name* */class Teacher :private string{ // teacher 中擁有string類型的成員 private:double salary; // 工資public:Teacher();Teacher(int _salary) : salary(_salary){}double GetSalary(){return salary;}void SetSalary(double salary){this->salary = salary;}// 難點(diǎn)const string& GetName() const{/** Teacher類是由string 類私有派生而來,所以,可以使用強(qiáng)制類型轉(zhuǎn)換,將Teacher類轉(zhuǎn)換成string類* 為了避免調(diào)用構(gòu)造函數(shù)創(chuàng)建新的對(duì)象,所以強(qiáng)制轉(zhuǎn)換成了string 的引用類型返回* 本方法返回一引用,指向調(diào)用本方法的Teacher 對(duì)象中繼承而來的string對(duì)象* */return (const string&)*this; //強(qiáng)轉(zhuǎn)}//using string::length(); //將字符串方法聲明為本類的公有方法/*返回當(dāng)前教師類對(duì)象姓名的字符串長度*/int GetLenght(){return string::length();}~Teacher();string nickName; // 使用組合關(guān)系實(shí)現(xiàn)比較簡單的has-a 關(guān)系protected:}; #endif //CHAPTER13_1_TEACHER_H

    4. 繼承和組合

    一張臉由多個(gè)類組合而成,頭發(fā)的不同總類從父類頭發(fā)那里繼承而來。

    繼承是is a 縱向關(guān)系–狗是哺乳動(dòng)物,戰(zhàn)士是英雄,橘貓是寵物–
    組合是has a 橫向關(guān)系–學(xué)生有書包,戰(zhàn)士有武器,

    繼承是C++與C最重要的區(qū)別,雖然C++也可以用C語言的編程習(xí)慣。

    總結(jié)

    以上是生活随笔為你收集整理的C++(22)--继承和派生的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。