C++ Primer 第十五章 面向對象程序設計 15.5訪問控制與繼承 練習和總結

15.5 訪問控制和繼承

在繼承體系中,有兩個地方需要用到訪問限定符,第一個地方是類中 ,protected修飾的成員可以在派生類中直接訪問,但是不能在用戶代碼中直接訪問

在派生類中我們只能通過派生類對象來訪問基類的protected數據成員,不能通過基類變量訪問基類的protected數據成員。

class A {
public:
	int pub_value;
protected:
	int pro_value;
};
class B :public  A {
public:
	B(const A&a){
		a.pro_value;//錯誤
	};;
	void func(const A& a) {
		a.pro_value;//錯誤
	}
	friend void fun_1(const A& a);
};
void fun_1(const A& a) {
	a.pro_value;//錯誤
}

第二個使用訪問限定符的地方是,在派生列表中,使用public,private和protected來修飾基類,表示使用什麼樣的方式來繼承基類中的成員。

使用public繼承的基類成員的訪問方式不變,即基類中修飾爲public的成員在派生類中依舊是public。private依舊是private,protected依舊是protected。

使用private繼承的,所有成員在派生類中都變爲private。

使用protected繼承的,public和protect成員變爲protected,private的成員還是private。

這樣繼承之後,成員的訪問限制就和普通的類一樣了。

繼承時的訪問限定會影響派生類向基類的類型轉換。

轉換規則如下:
在這裏插入圖片描述
總的來說就是一句話,在函數(外部定義的普通函數,成員函數,友元函數)如果可以使用派生類的對象訪問基類的成員(上面的三種函數對於類中可訪問的成員是不同的)那麼這個函數中可以進行類型轉換。

友元關係不可繼承,基類的友元只能訪問基類的數據成員。

書中的這個例子就很好
在這裏插入圖片描述
派生類的友元不能訪問基類對象的成員。 這裏和派生類的友元函數中不能用基類對象直接訪問基類protected修飾的成員對起來了。 因爲友元不能繼承和傳遞,它不是基類的友元,自然不能修改它。

每個類只負責各自成員的訪問權限。

改變繼承的成員的可訪問性

我們可以使用using 基類名::數據成員來保持基類成員的訪問控制。

下面的代碼使用private來繼承A但是修改了A數據成員的訪問限制。

class A {
	friend void func_1(const A& a);
public:
	int pub_value;
protected:
	int pro_value;
};
class B :private  A {
//public:
protected:
	using A::pub_value;
	using A::pro_value;
};
struct和class的區別

struct和class的區別有兩點,
1.struct默認成員爲public,class默認成員的訪問限制爲private
2.使用struct定義的派生類繼承基類被繼承時默認是public的方式,使用class定義的派生類繼承時默認是private。

練習

15.18

合法,因爲Pub_Derv是public繼承自Base,可以在用戶代碼中完成派生類向基類轉換。

Base* p= &d1;

不合法,因爲Prot_Derv和Pri_Derv是使用protected和private的方式繼承Base的,不能在用戶代碼中完成派生類向基類的類型轉換

p= &d2;
p=&d3;

合法,因爲dd1的類類型是public繼承自Pub_Derv,Pub_Derv採用public繼承自Base,所以訪問控制還是public類型的,可以在用戶代碼中完成派生類向基類轉換。

p=&dd1;

不合法,雖然Derived_from_Private,Derived_from_Protected分別public繼承自 Priv_Derv,Prot_Derv,但是Priv_Derv和Prot_Derv分別private和protect繼承自Base。
所以Base中的成員對於Derived_from_Private和Derived_from_Protected來說分別是private,private+protect的。所以不可以在用戶代碼中完成派生類向基類的轉換。

p=&dd2;
p=&dd3;
15.19

只有Derived_from_Private中函數是不合法的,其直接基類使用private繼承自Base,所以不能進行向Base的轉換,讓我意外的是,報錯的地方有兩個,一個是形參列表中的Base* ,一個是p=*this。

*p=this是很好理解,理由就是上面的理由,但是爲什麼形參會報錯。。按道理說,只要這個類存在,我就可以聲明爲形參呀,但是VS2017給出的報錯提示信息爲Base()不可訪問。

15.20

15.21

b.圖像基元

可以設置一個抽象基類,這個類包含一個純虛函數draw()用於畫出這個圖像的形狀。該類包含一個string類型的數據成員,表示這個類屬於什麼圖像的名字(方格,圓,球)。

15.22
class Shape{
	public:
	virtual void Shape()=0;
	protected:
	string name;
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章