當前位置:首頁 > 公眾號精選 > 嵌入式微處理器
[導讀]繼承和派生的概念 0 1 派生 通過特殊化已有的類來建立新類的過程,叫做“類的派生”, 原有的類叫做”基類”,新建立的類叫做“派生類”。 0 2 繼承 類的繼承是指派生類繼承基類的數(shù)據(jù)成員和成員函數(shù)。繼承用來表示類屬關系,不能將繼承理解為構成關系。 0 3






繼承和派生的概念






0 1
派生



通過特殊化已有的類來建立新類的過程,叫做“類的派生”, 原有的類叫做”基類”,新建立的類叫做“派生類”。



0 2
繼承



類的繼承是指派生類繼承基類的數(shù)據(jù)成員和成員函數(shù)。繼承用來表示類屬關系,不能將繼承理解為構成關系。



0 3
繼承派生的作用



  • 增加新的成員(數(shù)據(jù)成員和成員函數(shù))

  • 重新定義已有的成員函數(shù)

  • 改變基類成員的訪問權限






單一繼承






0 1
一般形式



   代碼格式:

 class 派生類名: 訪問控制 基類名 {         private: 成員聲明列表         protected: 成員聲明列表         public: 成員聲明列表 }

“冒號表示新類是哪個基類的派生類;訪問控制指繼承方式。

 

三個方式:public、protected、private



0 2
派生類的構造函數(shù)和析構函數(shù)



// 基類class Point { int x; int y;  public: Point(int a, int b) { x = a; y = b; cout << "init Point" << endl; } void showPoint() { cout << "x = " << x << ", y = " << y << endl; } ~Point() { cout << "delete Point" << endl; }};
// 派生類class Rect: public Point { int w; int h; public: // 調(diào)用基類的構造函數(shù)對基類成員進行初始化 Rect(int a, int b, int c, int d):Point(a, b) { w = c; h = d; cout << "init Rect" << endl; } void showRect() { cout << "w = " << w << ", h = " << h << endl; } ~Rect() { cout << "delete Rect" << endl; }};
int main() { Rect r(3, 4, 5, 6); r.showPoint(); r.showRect(); /** 輸出結果 init Point // 當定義一個派生類的對象時, 首先調(diào)用基類的構造函數(shù), 完成對基類成員的初始化 init Rect // 然后執(zhí)行派生類的構造函數(shù), 完成對派生類成員的初始化 x = 3, y = 4 // 調(diào)用基類成員函數(shù)showPoint(); w = 5, h = 6 // 調(diào)用派生類成員函數(shù)showRect(); delete Rect // 構造函數(shù)的執(zhí)行順序和構造函數(shù)的執(zhí)行順序相反, 首先調(diào)用派生類的析構函數(shù) delete Point // 其次調(diào)用基類的析構函數(shù) */}



0 3
類的保護成員



如果希望Rect中的showRect()函數(shù)可以一次顯示x、y、w、h。我們直接修改showRect()函數(shù)是不行的。

void showRect() { cout << "x = " << x << ", y = " << y << ", w = " << w << ", h = " << h << endl;}

報錯 error: 'x' is a private member of‘Point' 'y' is a private member of‘Point'  


x, y為Point類的私有成員,公有派生時,在Rect類中是不可訪問的。


我們還需要將基類Point中的兩個成員聲明為protected的屬性。


像這樣:

// 基類class Point { // 公有數(shù)據(jù)成員 protected: int x; int y;  public: Point(int a, int b) { x = a; y = b; cout << "init Point" << endl; } void showPoint() { cout << "x = " << x << ", y = " << y << endl; }};
// 派生類class Rect: public Point { int w; int h; public: // 調(diào)用基類的構造函數(shù)對基類成員進行初始化 Rect(int a, int b, int c, int d):Point(a, b) { w = c; h = d; cout << "init Rect" << endl; }     /** 公有派生, Point類中的受保護數(shù)據(jù)成員, 在Rect類中也是受保護的, 所以可以訪問  // 而通過公有繼承的基類私有的成員, 在派生類中是不可被訪問的    void showRect() {        cout << "x = " << x << ", y = " << y << ", w = " << w << ", h = " << h << endl;    }*/};
int main() { Rect r(3, 4, 5, 6); r.showPoint(); r.showRect();}



0 4
訪問權限和賦值兼容規(guī)則



根類中,對于成員的訪問級別有三種:public、protected、private


派生類中,對于成員的訪問級別有四種:public(公有)、protected(受保護)、private(私有)、inaccessible(不可訪問)


(1)公有派生和賦值兼容規(guī)則


公有派生


基類成員的訪問權限在派生類中基本保持不變。


  • 基類的公有成員在派生類中仍然是公有的

  • 基類的保護成員在派生類中仍然是受保護的

  • 基類的不可訪問的成員在派生類中仍然是不可訪問的

  • 基類的私有成員在派生類中變成了不可訪問的


總結:在公有派生的情況下,通過派生類自己的成員函數(shù)可以訪問繼承過來的公有和保護成員, 但是不能訪問繼承來的私有成員, 因為繼承過程的私有成員,變成了第四個級別,不可訪問的。


賦值兼容規(guī)則:


在公有派生的情況下, 一個派生類的對象可以作為基類的對象來使用的情況。


像這樣:

// 基類class Point { // 這里聲明成員屬性為受保護的 protected: int x; int y;  public: Point(int a, int b) { x = a; y = b; }  void show() { cout << "x = " << x << ", y = " << y << endl; }};
// 派生類class Rect: public Point { int w; int h; public: // 調(diào)用基類的構造函數(shù)對基類成員進行初始化 Rect(int a, int b, int c, int d):Point(a, b) { w = c; h = d; } void show() { cout << "x = " << x << ", y = " << y << ", w = " << w << ", h = " << h << endl; }};
int main() { Point a(1, 2); Rect b(3, 4, 5, 6); a.show(); b.show(); Point & pa = b; // 派生類對象初始化基類的引用 pa.show(); // 實際調(diào)用基類的show()函數(shù) Point * p = &b; // 派生類對象的地址賦值給指向基類的指針 p -> show(); // 實際也是調(diào)用基類的show()函數(shù) Rect * pb = &b; // 派生類指針 pb -> show(); // 調(diào)用派生類的show()函數(shù) a = b; // 派生類對象的屬性值, 更新基類對象的屬性值 a.show(); // 調(diào)用基類的show()函數(shù) /** x = 1, y = 2 x = 3, y = 4, w = 5, h = 6 x = 3, y = 4 x = 3, y = 4 x = 3, y = 4, w = 5, h = 6 x = 3, y = 4 */}


(2)“isa”和”has-a“的區(qū)別


繼承和派生 isa


比如一個Person類,派生出一個Student類,我們可以說Student就是Person,也就是 Student isa Person,而反過來則不行。


一個類用另一個類的對象作為自己的數(shù)據(jù)成員或者成員函數(shù)的參數(shù) has-a。


像這樣:

// 地址類class Address {};class PhoneNumber {};
// 職工類class Worker { String name; Address address; PhoneNumber voiceNumber;};

表示一個Worker對象有一個名字,一個地址,一個電話號碼,has-a的關系,包含的關系。


(3)私有派生


通過私有派生,基類的私有和不可訪問成員在派生類中是不可訪問的,而公有和保護成員這里就成了派生類的私有成員。

// 基類class Point { int x; int y;  public: Point(int a, int b) { x = a; y = b; }
void show() { cout << "x = " << x << ", y = " << y << endl; }};
// 派生類class Rect: private Point { int w; int h; public: Rect(int a, int b, int c, int d):Point(a, b) { w = c; h = d; } void show() { Point::show(); // 通過私有繼承, Point類中的公有成員show(), 在Rect中為私有 cout << "w = " << w << ", h = " << h << endl; }};
class Test: public Rect { public: Test(int a, int b, int c, int d):Rect(a, b, c, d) { } void show() { Rect::show();        //Point::show(); /** error: 'Point' is a private member of ‘Point’ 標明: 不可訪問基類Point中的成員 Rect類私有繼承自Point類, 所以Point中的私有成員x, 私有成員y, 在Rect類中為不可訪問: Point類中公有成員show(), 在Rect中變私有 Test類公有繼承自Rect類, 所以在Rect中成員x, 成員y, 仍然是不可訪問, Rect::show()還是public, 但是Point::show()不可訪問 */ }};

因為私有派生不利于進一步派生, 因而實際中私有派生用得并不多。


(4)保護派生保護派生使原來的權限都降一級使用


即private變?yōu)椴豢稍L問,protected變?yōu)閜rivate,public變?yōu)閜rotected。


限制了數(shù)據(jù)成員和成員函數(shù)的訪問權限,因此在實際中保護派生用得也不多。


比如:我們在上個例子中,Rect類保護派生于Point,則在Test類中Point::show();就可以使用啦!






多重繼承






0 1
一個類從多個基類派生



代碼格式:

class 派生類名: 訪問控制 基類名1訪問控制 基類名2… { //定義派生類自己的成員}


像這樣:

// 基類A, 也叫根類class A { int a;  public: void setA(int x) { a = x; }  void showA() { cout << "a = " << a << endl; }};
// 基類B, 也叫根類class B { int b; public: void setB(int x) { b = x; } void showB() { cout << "b = " << b << endl; }};
// 多重繼承, 公有繼承自類A, 私有繼承自類Bclass C: public A, private B { int c; public: void setC(int x, int y) { c = x; setB(y); } void showC() { showB(); cout << "c = " << c << endl; }};
int main() { C c; c.setA(53); // 調(diào)用基類setA()函數(shù) c.showA(); // 調(diào)用基類showA()函數(shù) c.setC(55, 58); // 調(diào)用派生類C的setC()函數(shù) c.showC(); // 調(diào)用派生類C的showC()函數(shù) // 派生類C私有繼承自基類B, 所以基類B中私有成員b, 在派生類C中不可訪問, 基類B中公有成員setB(), showB()在派生類C中變私有. 在main()函數(shù)中不可訪問    // c.setB(60); // error: 'setB' is a private member of 'B'    // c.showB(); // 'showB' is a private member of 'B' /** a = 53 b = 58 c = 55 */}






二義性及其支配規(guī)則





對基類成員的訪問必須是無二義性的,如果一個表達式的含義可以解釋為可以訪問多個基類中的成員,則這種對基類成員的訪問就是不確定的,稱這種訪問具有二義性。



0 1
作用域分辨符和成員名限定



代碼格式:

類名::標識符

:: 為作用域分辨符,"類名"可以是任一基類或派生類名,“標識符”是該類中聲明的任一成員名,


像這樣:

// 基類A, 也叫根類class A { public: void func() { cout << "A func" << endl; }};
// 基類B, 也叫根類class B { public: void func() { cout << "B func" << endl; } void gunc() { cout << "B gunc" << endl; }};
// 多重繼承class C: public A, public B { public: void gunc() { cout << "C gunc" << endl; } void hunc() { /** 這里就具有二義性, 它即可以訪問A類中的func(), 也可以訪問類B中的func() */ //func(); // error: Member 'func' found in multiple base classes of different types } void hunc1() { A::func(); } void hunc2() { B::func(); }};
int main() { C c;    //c.func(); //具有二義性 c.A::func(); c.B::func(); c.B::gunc(); c.C::gunc(); c.gunc(); c.hunc1(); c.hunc2(); /** 輸出結果 A func B func B gunc C gunc C gunc // 如果基類中的名字在派生類中再次聲明, 則基類中的名字就被隱藏. 如果我們想要訪問被隱藏的基類中的成員則使用作用域分辨符B::gunc(); A func B func */}



0 2
派生類支配基類的同名函數(shù)



如果派生類定義了一個同基類成員函數(shù)同名的新成員函數(shù)(具有相同參數(shù)表的成員函數(shù)),派生類的新成員函數(shù)就覆蓋了基類的同名成員函數(shù)。


在這里,直接使用成員名只能訪問派生類中的成員函數(shù),使用作用域運算符,才能訪問基類的同名成員函數(shù)


派生類中的成員函數(shù)名支配基類中的同名的成員函數(shù)名,這稱為名字支配規(guī)則。


如果一個名字支配另一個名字,則二者之間不存在二義性,當選擇該名字時,使用支配者的名字。


例如上個例子中

c.gunc() // 輸出”C gunc”, 基類B中的gunc成員函數(shù)被支配了c.B::gunc(); // 加上作用域分辨符, 來使用被支配的成員






總結





C++繼承可能更靈活, 并且支持三種派生方式。

我們在學習一門語言的時候, 更應該把精力放在它的特性上面, 不應該用什么語言, 都用自己所擅長語言的思考方式, 實現(xiàn)方式等, 要學會發(fā)揮該語言的優(yōu)勢所在。


-END-


來源 :老九學堂




推薦閱讀



【01】C/C++干貨:函數(shù)指針與指針函數(shù)
【02】C++之智能指針的學習總結
【03】史上最全!一文讓你學完C++,干貨收藏?。?!
【04】C++之標準庫的學習總結
【05】C++基礎知識!初學者必看!


免責聲明:整理文章為傳播相關技術,版權歸原作者所有,如有侵權,請聯(lián)系刪除

免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉