一、什麼是繼承?
**淺顯的說,繼承就是父類的公有(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. 注意在實際中在繼承體系裏面最好不要定義同名的成員。**
當子類的成員函數中具有和父類相同的成員函數,則會造成隱藏。
並且當分別調用時,訪問的是自己的成員函數
用底層彙編的調用看看