1. 程式人生 > ><C++ - 繼承01> 2018-01-22

<C++ - 繼承01> 2018-01-22

參數 == ostream str 相關 getch 一個 不能訪問 自己

01、繼承:

#include <iostream>
using namespace std;
/*
    回顧上節的內容:
        const 重載
        運算符重載  ->  () 函數對象


    今天的內容   繼承
        比如:   人  -->身高  年齡  ...吃飯  睡覺  打豆豆  --> 成員函數   成員變量
            小學生   吃飯 睡覺  打豆豆  寫作業  上學  身高  年齡  學號
            大學  吃飯 睡覺 大打豆豆  談戀愛  寫論文  玩遊戲  學習  身高 年齡  績點

    幾個類  -->相似的屬性  行為
    繼承  某個類  繼承一個類(基類/父類)中所有的成員(成員變量/函數)加上自己的屬性/行為成為一個新的類(派生類/子類)

    繼承:
        1.吸收父類成員(除去構造和析構)
            子類會吸收父類的所有成員
        2.調整父類的成員
            2.1訪問控制
                2.1.1 繼承方式     public  private  protected
                2.1.2 父類的成員  public  private  protected
                        訪問權限  private < protected < public
                    父類的 private 成員  子類中不能訪問
                    其余的成員 就按照繼承方式中最安全的一種 作為子類的屬性
                    繼承方式 默認私有
                2.2 隱藏
                     子類中定義一個父類相同的成員變量或者成員函數  //父類中的成員函數或者變量就會被隱藏  通過子類對象訪問  訪問到的是新的函數/變量
                     //隱藏的是父類繼承過來的函數和成員(子類中生效)
                     //如果說子類中的函數和父類繼承的函數  函數名相同  參數不一樣  繼承的函數和新寫的函數構造重載

                     //子類不影響父類
        3.添加新成員
            子類中添加新成員變量/函數   實現新功能
         基類  構造  析構  -->沒辦法繼承   子類要寫自己的構造和析構
          子類的構造:
                    1.它必須調用父類的構造函數  (如果沒有顯示調用 那麽就隱性調用了默認的構造函數)
                    2.需要顯示調用 必須使用初始化形參列表
                    3.先調用父類構造  然後在調用子類構造
                    4.調用順序和形參列表中的順序無關
          子類的析構:
                    1.析構會調用父類的析構   先調用子類析構   然後調用父類析構
                    2.可以默認調用  不需要顯示調用
                
                父類的函數  可以訪問父類的成員
                修改  訪問父類中的私有成員  --> 父類公有函數訪問

    多繼承:   一個類繼承多個父類

        //開發效率  -->提高的開發效率

*/ //=======================================類函數==================================== class father { private: int weight; // 體重 float height; // 身高 public: int wealth; father(){ cout << "father的構造" << endl; } father(int x, float y, int z) :weight(x), height(y), wealth(z) { }
~father(){ cout << "father的析構" << endl; } void play(){ cout << "father的play" << endl; } void eat(){ cout << "father的eat" << endl; } }; class son:public father // 後面是繼承父類: // 1.父類不是只有一個子類; // 2.子類可能不止有一個父類
// 如果是繼承多個父類 逗號隔開 { public: int age; // 年齡 float height; // 身高 int wealth; son():father() // 調用了父類的構造函數 { cout << "調用了子類的構造函數" << endl; // weight; 父類的私有成員 子類中不能訪問 //eat(); // 調用父類中eat() } /** 父類的成員 -->父類的構造函數 初始化 子類 初始化子類的成員 子類 繼承了父類的成員 -->繼承過來的成員 可以重新賦值 */ son(int x, float y, int z) :age(x), height(y), wealth(z), father(x,y,z) // 有參構造 { } void play(){ cout << "son的play" << endl; } }; int main() { father ft; cout << sizeof(ft) << endl; son sn; cout << sizeof(sn) << endl; sn.height; sn.eat(); sn.play(); getchar(); return 0; }

02、多繼承:

#include <iostream>
using namespace std;
/*
    多繼承  繼承兩個或者多個基類的所有成員
        1.繼承  子類會調用父類的構造函數  調用順序只和繼承順序相關
        2.析構  和構造函數順序相反
        3.要訪問某個類繼承過來的成員  基類名::成員名  訪問(註意訪問權限)

菱形繼承    A派生B和C    B和C共同派生D    D就有來自A的兩份拷貝(一份來自B 一份來自D)
   虛繼承  主要解決菱形繼承   (關鍵字:virtual)

   虛繼承不影響B和C  影像的是D
    如果B  和C 只有一個加virtual  那麽和繼承順序有關


   一般的話  不建議使用多繼承
*/

class fruit   // 水果
{
public:
    int color;
    fruit(){ cout << "水果類的構造函數" << endl; }
    ~fruit(){ cout << "水果類的構造函數" << endl; }
    void eat()
    {
        cout << "可以生吃" << endl;
    }
};
class vegetable   // 蔬菜
{
public:
    int color;
    vegetable(){ cout << "蔬菜類的構造函數" << endl; }
    ~vegetable(){ cout << "蔬菜類的構造函數" << endl; }
    void cook()
    {
        cout << "煮熟吃" << endl;
    }
};
class tomato :public fruit, public vegetable  // 多繼承  用逗號隔開
{
    // 先構造水果類 然後構造蔬菜類
public:
    int color;
    tomato() :vegetable(), fruit()
    {
        /**
            構造中初始化形參列表順序  不影響調用順序
        */
    }
    void see()
    {
        vegetable::color = 2;    // 從類vegetable中繼承的color
        fruit::color = 5;
        color = 6;
        cout << vegetable::color << fruit::color << color << endl;
    }
};
//================================================例子=============================================
class A
{
public:
    int x;
};
class B :virtual public A
{

};
class C :virtual public A
{

};
/*
    車 四個輪子  -->B四個輪子  C四個輪子  -->D  8個輪子
*/
class D :public B, public C
{
public:
    void print()
    {
        B::x = 3;  // 虛繼承  在最終的孫子類中  只留一個祖父類的拷貝
        C::x = 4;
        cout << B::x << C::x << x << endl;
    }
};
int main()
{
    D d;
    d.print();
    {
        tomato ta;
        ta.cook();   // 煮熟吃
        ta.eat();    // 生吃
        ta.see();
    }
    
    getchar();
    return 0;
}

/*
    作業: 
        人類         身高  體重  吃飯睡覺
        男人類         運動
        學生類       學習  考試
        -->派生出  男學生類     打印出吃飯睡覺


    // 預防菱形繼承


*/

<C++ - 繼承01> 2018-01-22