C++ 繼承 多態

繼承和派生

面向對象的語言有三種特性封裝,繼承和多態。
C++的1可重用性是通過繼承這一機制來實現的。

繼承的基本概念

繼承是類之間定義的一種重要關係
一個B類繼承A類,或稱從A類派生B類
類A稱爲基類(父類),類B稱爲派生類(子類)
見如下代碼:

class A 
{
    public:
      func()
      {

      }
      int a;
};

class B :public A         //出現這樣的形式就是類B繼承於類A(類B包含於類A中所有的東西)
{
    public:
    funB()
    {
        cout << a << endl;
    }
};

下面舉個例子:

 #include "stdafx.h"
#include <string>

using namespace std;

class Student
{
public:
    Student(int id, string name)
    {
        this->id = id;
        this->name = name;
    }
    void printS()
    {
        cout << "id = " << this->id << ", name = " << this->name << endl;
    }
private:
    int id;
    string name;

};

//創建一個新的學生類,增加score、功能
class Student2 :public Student
{
public:
    Student2(int id,string name,int score) :Student(id,name)//利用父類構造函數來給子類初始化
    {
        this->score = score;

    }
    void printS()
    {
        Student::printS();
        cout << "score = " << this->score << endl;
    }
private:
    int score;

};

int main()
{
    Student2 s2(1, "zhangsan", 80);
    s2.printS();


    return 0;
}

這裏寫圖片描述
* 注意:
* 公有繼承public(形式:class B :public A)
父類的public成員變量,在繼承類的內部和外部都可以訪問
父類的protected成員變量,在繼承類的內部可以訪問,在類的外部不可以訪問。
父類的private成員變量,在繼承類的內部和外部都不可以訪問。
這裏寫圖片描述
* 保護繼承protected(形式:class B :protected B)
父類的public成員變量,在繼承類的內部可以訪問,外部不可以訪問。但在繼承類的公有繼承子類中此成員變量可以被訪問,所以父類中的public成員變量在變爲protected變量。
父類的protected成員變量,在繼承類的內部可以訪問,在類的外部不可以訪問。在繼承類中爲protected變量.
父類的private成員變量,在繼承類的內部和外部都不可以訪問。

類的賦值兼容原則

  1. 子類對象可以直接調用父類中的成員函數
  2. 子類對象可以直接賦值給父類對象。
  3. 子類對象可以直接初始化父類對象。
  4. 父類引用可以直接引用子類對象。
  5. 父類指針可以直接指向子類對象。
Parent *pp = NULL;  //父類指針  
Child *cp = NULL;  //子類指針  

parent p;  //父類對象  
Child c;   //子類對象  

pp = &c;  //ok  c的內存佈局能夠滿足父類指針的全部需求,可以用一個兒子的對象地址給父類指針賦值
cp = &p;  //error

子類的構造和析構

在調用子類的構造函數的時候,一定會調用父類的構造函數。父類先構造,子類後構造。

class Parent {
public:
    Parent(int a)
    {
        this->a = a;
        cout << "Parent(int)" << endl;
    }

    ~Parent()
    {
        cout << "~Parent()" << endl;
    }

protected:
    int a;
};

class Child :public Parent
{
public:
    Child(int a, int b) :Parent(a)
    {
        this->b = b;
        cout << "Child(int a,int b)" << endl;
    }
    void PrintC()
    {
        cout << "a = " << a << ", b = " << b << endl;
    }
    ~Child()
    {
        cout << "~Child()" << endl;
    }
private:
    int b;
};

int main()
{
    Child c(10, 20);
    c.PrintC();
    return 0;
}

這裏寫圖片描述

多繼承和虛繼承

多繼承:

class Father
{

};

class Mother
{

};

class Child :public Father,public Mother
{

};

虛繼承:
當有兩個父類都繼承同一個爺爺類時,那麼子類在調用爺爺類的成員函數的時候就會出現拷貝多分成員變量,因而出現歧義,此時須將父類繼承爺爺類改爲虛繼承。

class father :virtual public Grandfather
{

};

多態

如果有幾個以上相似而不完全相同的對象,有時人們要求在向它們發出同一個消息時,它們的反應各不相同,分別執行不同的操作。這種現象就是多態現象。
C++中所謂的多態是指,由繼承而產生的相關的不同的類,其對象對同一消息會作出不同的響應。
方法:如果在父類和子類的成員函數中都有一個相同名字的成員函數,那麼在外界函數調用子類或者父類時,要想傳遞進來的是子類,就調用子類的成員函數;若傳遞進來的是父類,就調用父類的成員函數,那麼就得讓父類的成員函數稱爲虛函數。即在父類成員函數名的最前面加virtual關鍵字。
* 多態發生的三個必要條件:
1. 要有繼承。
2. 要有虛函數重寫。
3. 父類指針或引用 指向 子類對象。

虛析構函數

在多態時,要調用析構函數時,注意在父類的析構成員函數前加virtual。

virtual ~A()
    {
        cout << "~A()..." << endl;
        if (this->p != NULL)
        {
        delete[] this->p;
            this->p = NULL;
        }

這樣才能先析構子類再析構父類。

重載 重定義 重寫

  1. 重載:一定發生在同一個作用域下。
  2. 重定義:是發生在兩個不同的類中,一個是父類,一個是子類。
        1. 普通函數重定義。 //如果父類的普通成員函數,被子類重寫,說是重定義,
        2.虛函數重寫。 //如果父類的虛函數,被子類重寫,就是虛函數重寫。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章