繼承

一、什麼是繼承?

   **淺顯的說,繼承就是父類的公有(public)可見的部分,子類會繼承父類公有的成員**
   **舉個栗子:**
class Person
{
public:
	void Display()
	{ 
		cout << "this is person"<< endl;
	}
protected:
	char* _name; // 姓名
};

class Student : public Person
{
public:

	void Print()
	{
		cout << _num << _name << endl;
	}
protected:
	int _num; // 學號
};
**滿足這樣的格式叫做繼承**

在這裏插入圖片描述

二、繼承的內容?

**繼承相當於是子類複用了父類公有的成員,這樣的好處是減少了代碼量**
**三種繼承關係下父類成員的在子類類的訪問關係變化**

在這裏插入圖片描述

**相當於子類繼承父類的public部分,其他protected、private的繼承方式會在子類中也爲protected、private不可訪問**

總結:

**1、父類的私有成員在子類中是不能被訪問的,如果一些父類成員不想被父類對象直接訪問,但需要在子類中能訪問,就定義爲保護成員。可以看出保護成員限定符是因繼承纔出現的。**
**2. public繼承是一個接口繼承,保持is-a原則,每個父類可用的成員對子類也可用,因爲每個子類對象也都是一個父類對象。**
**3. protetced/private繼承是一個實現繼承,基類的部分成員並未完全成爲子類接口的一部分,是 has-a 的關係原則,所以非特殊情況下不會使用這兩種繼承關係,在絕大多數的場景下使用的都是公有繼承。**

is-a 和 has-a
在這裏插入圖片描述

**4. 不管是哪種繼承方式,在派生類內部都可以訪問基類的公有成員和保護成員,但是基類的私有成員存在但是在子類中不可見(不能訪問)。**
**5. 使用關鍵字class時默認的繼承方式是private,使用struct時默認的繼承方式是public,不過最好顯式的寫出繼承方式。**
**6. 在實際運用中一般使用都是public繼承,極少場景下才會使用protetced/private繼承.**

分別採用public、protected、private的方式來繼承父類


class Person
{
public:
	void Display()
	{
		cout << "this is Person" << endl;
	}
protected:
	char* _name;
private:
	char* _id;
};

class Student1 :protected Person
{
private:
	int _age;
};

class Student2 :private Person
{
private:
	int _age;
};

class Student :public Person
{
private:
	char* _id;
};
void TestPPP()
{
	Person p;
	Student s;
	Student1 s1;
	Student2 s2;
	p.Display();
	s.Display();
	s1.Display();
	s2.Display();
}

運行上面代碼
在這裏插入圖片描述
發現到以private、protected方式繼承編譯會出現錯誤,錯誤顯示爲不可訪問,所以當子類是以private、protected繼承的,在類外定義並訪問成員函數是訪問不了的。

繼承與轉換–賦值兼容規則–public繼承

**
1. 子類對象可以賦值給父類對象(切割/切片)
2. 父類對象不能賦值給子類對象
3. 父類的指針/引用可以指向子類對象
4. 子類的指針/引用不能指向父類對象(可以通過強制類型轉換完成)**

切片/切割
在這裏插入圖片描述

class Person
{
public:
	void Display()
	{
		cout << _name << endl;
	}
protected:
	string _name; // 姓名
};
class Student : public Person
{
public:
	int _num; // 學號
};
void Test()
{
	Person p;
	Student s;
	// 1.子類對象可以賦值給父類對象(切割 /切片)
	p = s;
	// 2.父類對象不能賦值給子類對象
	//s = p;
	// 3.父類的指針/引用可以指向子類對象
	Person* p1 = &s;
	Person& r1 = s;
	// 4.子類的指針/引用不能指向父類對象(可以通過強制類型轉換完成)
	Student* p2 = (Student*)& p;
	Student& r2 = (Student&)p;
	// 這裏會發生什麼?
	p2->_num = 10;
	r2._num = 20;
}

在這裏插入圖片描述
在這裏插入圖片描述

**繼承體系中的作用域
1. 在繼承體系中基類和派生類都有獨立的作用域。
2. 子類和父類中有同名成員,子類成員將屏蔽父類對成員的直接訪問。(在子類成員函數		中,可以使用 基類::基類成員 訪問)--隱藏--重定義
3. 注意在實際中在繼承體系裏面最好不要定義同名的成員。**

當子類的成員函數中具有和父類相同的成員函數,則會造成隱藏。
並且當分別調用時,訪問的是自己的成員函數
用底層彙編的調用看看
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章