国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

面向對象程序設計之訪問控制、繼承與拷貝控制

2019-11-11 01:31:14
字體:
來源:轉載
供稿:網友

訪問控制與繼承: 一個類使用PRotected關鍵字來聲明那些希望與派生類分享但是不想被其他公共訪問的成員。其性質如下: (1)和私有成員類似,受保護的成員對類的用戶是不可訪問的 (2)和公有成員類似,受保護的成員對于派生類的成員和友元來時是可訪問的。 (3)派生類的成員或友元只能通過派生類對象訪問 基類的受保護成員。派生類對于一個基類對象中的受保護成員沒有任何訪問特權

這里寫圖片描述


某個類對其繼承而來的成員的訪問權限受兩個因素的影響: (1)基類中該成員的訪問說明符 (2)派生類的派生列表中的訪問說明符

這里寫圖片描述 對基類成員的訪問權限只與基類中的訪問說明符有關。派生訪問說明符的目的是控制派生類用戶(包括派生類的派生類在內)對于基類成員的訪問權限

這里寫圖片描述

派生訪問說明符還可以繼承自派生類的新類的訪問權限。

這里寫圖片描述


派生類向基類轉換的可訪問性: 對于代碼中的某個給定節點來說,如果基類的共有成員是可訪問的,則派生類向基類的類型轉換也是可訪問的。反之,則不行。 這里寫圖片描述 這里寫圖片描述

//用戶代碼可以使用派生類向基類轉換如果派生類繼承基類的方式是公有的,其他方式則不行//考慮類base和它的派生類已知Base *p=&d1;//d1的類型是Pub_Derv,正確p=&d2;//d2的類型是Priv_Derv,錯誤p=&d3;//d3的類型是Prot_Derv,錯誤p=&dd1;//dd1的類型是Derived_from_public,正確p=&dd2;//dd2的類型是Derived_from_private,錯誤p=&dd3;//dd3的類型是Derived_from_protected,錯誤

友元關系不具有繼承性,每個類負責控制各自成員的訪問權限

這里寫圖片描述


當我們需要改變派生類繼承的某個名字的訪問級別,可以通過使用using聲明。

class Base{public: std::size_t size() const{return n;}protected: std::size_t n;};class Derived:private Base //Base的成員在Derived是私有的。{public: using Base::size;protected: using Base::n;//改變訪問權限};

默認的繼承保護級別:

這里寫圖片描述


繼承中的類作用域:

當存在繼承關系時,派生類的作用域嵌套在其基類的作用域之內。如果一個名字在派生類的作用域內無法正確解析,則編譯器將繼續在外層的基類作用域尋找該名字的定義。


派生類的成員將隱藏同名的基類成員

這里寫圖片描述

我們可以通過作用域運算符來使用隱藏的成員。除了覆蓋繼承而來的虛函數之外,派生類最好不要重用其他定義在基類的名字。

這里寫圖片描述


如果派生類(內層作用域)的成員與基類(外層作用域)的某個成員同名,則派生類將在其作用域隱藏該基類成員,即使派生類成員和基類成員的形參列表不一致。

這里寫圖片描述


通過基類調用隱藏的虛函數,調用的時候主要是看是什么類的指針,是否有虛函數覆蓋

#include <iostream>class Base{public: Base(int v):v(v){} virtual int fcn() { return v; } int v=0;};class D1:public Base{public: D1(int d1):Base(d1){} int fcn(int d1) { return d1+1; } virtual void f2(){std::cout<<"f2() in D1"<<std::endl;}};class D2:public D1{public: D2(int dd):D1(dd){} int fcn(int d2) { return d2; } int fcn() { return v+100; } void f2(){std::cout<<"f2() in D2"<<std::endl;}};int main(){ Base b(10); D1 d1(10); D2 d2(10); Base *bp1=&b,*bp2=&d1,*bp3=&d2; std::cout<<bp1->fcn()<<std::endl;//10,虛調用,Base::fcn() std::cout<<bp2->fcn()<<std::endl;//10,虛調用,Base::fcn() std::cout<<bp3->fcn()<<std::endl;//110,調用D2::fcn() D1 *d1p=&d1; D2 *d2p=&d2;// bp2->f2();//錯誤,base沒有f2的成員 d1p->f2();//D1::f2() d2p->f2();//D2::f2() Base *p1=&d2; D1 *p2=&d2; D2 *p3=&d2; //p1->fcn(42);//錯誤,Base沒有fcn(int) std::cout<< p2->fcn(42)<<std::endl;//43,D1::fcn(42) std::cout<< p3->fcn(42)<<std::endl;//42,D2::fcn(42) return 0; }

虛折構函數: 繼承關系對基類拷貝控制最直接的影響是基類通常應該定義一個虛折構函數,這樣我們就能動態分配繼承體系中的對象了。如果基類的折構函數不是虛函數,則delete一個指向派生類對象的基類指針將產生未定義的行為

Quote *itemp=new Quote;delete itemp;//調用Quote的折構函數itemp=new Bulk_quote;delete itemp;//調用Bulk_quote的折構函數

基類或派生類的合成拷貝控制成員的行為與其他合成的構造函數、賦值運算符或折構函數類似,即它們對類本身的成員依次進行初始化,賦值或銷毀操作。此外,這些合成的成員還負責使用直接基類中對應的操作對一個對象的直接基類進行初始化、賦值或銷毀操作(從上到下)。

對于派生類的折構函數來說,它除了銷毀派生類自己的成員外,還負責銷毀派生類的直接基類,該直接基類又銷毀它自己的直接基類,以此類推直至繼承鏈的頂端。(自下而上)

某些定義基類的方式可能導致有的派生類成員成為被刪除的函數

這里寫圖片描述

class B{public: B(); B(const B&)=delete; //其他成員,不含移動構造函數};class D:public B{ //沒有聲明任何構造函數};D d;//正確。D的合成默認構造函數使用B的默認構造函數D d2(d);//錯誤,D的合成拷貝構造函數是刪除的。D d3(std::move(d));//錯誤,隱式使用D的被刪除的拷貝構造函數//因為Quote定義了折構函數而不能擁有合成的移動操作,因此當我們移動Quote對象時實際使用的是合成的拷貝操作。

因為基類缺少移動操作會阻止派生類擁有自己的合成移動操作,所以當我們卻是需要執行移動操作時應該首先在基類進行定義。但必須顯式的定義這些成員。

這里寫圖片描述


當派生類定義拷貝或移動操作時,該操作負責拷貝或移動包括基類部分成員在內的整個對象。 在默認情況下,基類默認構造函數初始化派生類對象的基類部分。如果我們想拷貝或移動基類部分,則必須在派生類的構造函數初始值列表中顯式地使用基類的拷貝或移動構造函數

class B {/*......*/};class D:public Base{public: //Base(d)會匹配Base的拷貝構造函數。D類型的對象d被綁定到該構造函數的Base&形參上。Base的拷貝構造函數負責將d的基類部分拷貝給要創建的對象。 D (const D& d):Base(d)//拷貝基類成員 /* D的成員的初始值 */{......} D (D&& d):Base(std::move(d))//移動基類成員 /* D的成員的初始值 */{......}};

派生類的賦值運算符也必須顯式地為其基類部分賦值。

D D&::Operator=(const D &rhs){ Base::operator=(rhs);//為基類部分賦值 ..... return *this}

派生類折構函數只負責銷毀由派生類自己分配的資源

class D:public Base{public: //Base::~Base自動執行 ~D(){//用戶定義};};

我們可以使用基類名的using聲明語句來說明派生類繼承基類構造函數。但是一個構造函數的using聲明不會改變該構造函數的訪問級別。而且,一個using聲明的語句不能指定explicit或constexpr.

class B:public A{public: using A::A;//繼承基類A的構造函數};

當一個基類構造函數含有默認實參,這些實參并不會被繼承。相反,派生類將獲得多個繼承的構造函數,其中每個構造函數分別省略掉一個含有默認實參的形參。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 天峻县| 黔江区| 广灵县| 清远市| 镇赉县| 方山县| 新源县| 隆子县| 凤冈县| 岳池县| 洪泽县| 河西区| 鸡西市| 宿松县| 万全县| 旅游| 同心县| 墨玉县| 子长县| 土默特左旗| 玉龙| 平果县| 淮滨县| 库伦旗| 常州市| 巨鹿县| 屏南县| 古交市| 西乌珠穆沁旗| 北票市| 奉化市| 团风县| 江门市| 马山县| 长阳| 安多县| 烟台市| 河曲县| 定边县| 北京市| 岳阳县|