繼承

面向對象程序設計中最重要的一個概念是繼承。繼承允許我們依據另一個類來定義一個類,這使得創建和維護一個應用程序變得更容易。這樣做,也達到了重用代碼功能和提高執行時間的效果。
當創建一個類時,您不需要重新編寫新的數據成員和成員函數,只需指定新建的類繼承了一個已有的類的成員即可。這個已有的類稱爲基類,新建的類稱爲派生類。
繼承有三種繼承方式:公有繼承, 保護繼承,私有繼承。如下圖所示:
這裏寫圖片描述
一個簡單的公有繼承:

class Person//父類(基類)
{
public:
    Person()
    {
        cout << "Person" << endl;
    }
private:
    int _a;
};
class Student : public Person//子類(派生類)
{
public:
    Student()
    {
        cout << "Student" << endl;
    }
private:
    int _b;
};

總結:
1. 基類的私有成員在派生類中是不能被訪問的,如果一些基類成員不想被基類對象直接訪問,但需要在派生類中能訪問,就定義爲保
護成員。可以看出保護成員限定符是因繼承纔出現的。
2. public繼承是一個接口繼承,保持is-a原則,每個父類可用的成員對子類也可用,因爲每個子類對象也都是一個父類對象。
3. protetced/private繼承是一個實現繼承,基類的部分成員並未完全成爲子類接口的一部分,是has-a 的關係原則,所以非特殊情
況下不會使用這兩種繼承關係,在絕大多數的場景下使用的都是公有繼承。
4. 不管是哪種繼承方式,在派生類內部都可以訪問基類的公有成員和保護成員,但是基類的私有成員存在但是在子類中不可見(不能
訪問)。
5. 使用關鍵字class時默認的繼承方式是private,使用struct時默認的繼承方式是public,不過最好顯示的寫出繼承方式。
6. 在實際運用中一般使用都是public繼承,極少場景下才會使用protetced/private繼承。

繼承與轉換-賦值兼容規則(公有繼承):

1、子類的對象可以賦值給父類(切片)
2、父類的對象不可以賦值給子類
3、父類的指針和引用賦值給子類
4、子類的指針和引用不可以賦值給父類(可以強制類型轉換)

class Person//父類(基類)
{
public:
    Person()
    {
        cout << "Person" << endl;
    }
private:
    int _a;
};
class Student : public Person//子類(派生類)
{
public:
    Student()
    {
        cout << "Student" << endl;
    }
private:
    int _b;
};
void test()
{
    Person p;
    Student s;
    p = s;//子類可以賦值給父類
    //s = p;//父類不能賦值給子類
    Person* p1 = &s;//父類的指針和引用可以賦值給子類
    Person& p2 = s;
    //Student* s1 = &p;//子類的指針和引用不可以賦值給父類
    //Student& s2 = p;
    Student* s3 = (Student*)&p;//但是可以強制類型轉換賦值給父類
    Student& s4 = (Student&)p;
}

我們用下圖來解釋切片到底是一個什麼東西:
這裏寫圖片描述

隱藏:

子類和父類中有同名成員,子類成員將屏蔽父類對成員的直接訪問。(在子類成員函數中,可以使用基類::基類成員訪問)–隱藏(重定義)

簡單明瞭來說就是就是一個在基類一個在派生類中,函數名相同,不構成重寫就構成隱藏。不過這裏的重寫下面提到,這裏先這樣寫着。

下面我們再來說說派生類的六大默認成員函數:
在我們的派生類中,調用構造函數時,會有一個神奇的事情發生,它先會對在基類繼承下來的成員進行初始化,然後再對派生類的成員進行初始化。其他四個和構造函數一樣先調用父類的相對應的函數,然後派生類的,不過的是,析構函數有點區別,析構函數先對派生類的成員進行清理,在對父類的成員進行清理,畢竟棧上的規則爲後進先出。
拿一個簡答的構造函數舉個例子吧:

#include<string>
class Person
{
public:
    Person(const char* a)
        :_a(a)
    {}
    Person(const Person& p)
        :_a(p._a)
    {}
protected:
    string _a;
};
class Student : public Person
{
public:
    Student(const char* a,int b)
        :Person(a)
        ,_b(b)
    {}
    Student(const Student& s)
        :Person(s)
        ,_b(s._b)
    {}
private:
    int _b;
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章