C++中繼承(inheritance)詳解及其作用介紹

概述

面向對象程序設計中最重要的一個概念是繼承 (inheritance). 繼承允許我們依據另一個類來定義一個類, 這使得創建和維護一個應用程序變得更統一. 這樣做也達到瞭重用代碼功能和提高執行效率的效果.

在這裡插入圖片描述

類的概念

一個類中包含瞭若幹數據成員和成員函數. 不同的類中的數據成員和成員函數各不相同. 但是有時兩個類的內容基本相同. 例如:

在這裡插入圖片描述

繼承的概念

繼承 (inheritance) 就是在一個已存在的類的基礎上建立一個新的類.

  • 已存在的類: 基類 (base class) 或父類 (father class)
  • 新建立的類: 派生類 (derived class) 或子類 (son class)

在這裡插入圖片描述

一個新類從已有的類獲得其已有特性, 稱為類的繼承.

  • 通過繼承, 一個新建的子類從已有的父類那裡獲得父類的特性
  • 派生類繼承瞭基類的所有數據成員和成員函數, 並可以對成員做必要的增加或調整

從已有的類 (父類) 產生一個新的子類, 稱為類的派生.

  • 類的繼承是用已有的類來建立專用新類的編程技術
  • 一個基類可以派生出多個派生類, 每一個派生類又可以作為基類再派生出新的派生類. 因此基類和派生類是相對而言的
  • 派生類是基類的具體化, 而基類則是派生類的抽象

單繼承

單繼承 (single inheritance) 指一個派生類隻從一個基類派生.

  • 單繼承關系形成的層次是一個樹形結構
  • 箭頭表示繼承的方向, 從派生類指向基類

在這裡插入圖片描述

多重繼承

多重繼承 (multiple inheritance) 是指一個派生類有兩個或多個基類. 派生類不僅可以從一個基類派生, 也可以從多個基類派生.

在這裡插入圖片描述

派生類

派生類的聲明方式:

class 派生類名:[繼承方式]基類名{
    派生類新增加的成員
};

成員訪問限定符 (默認 private):

  • public (公用的)
  • private (私有的)
  • protected (受保護的)

繼承方式包括 (默認 private):

  • public (公用的)
  • private (私有的)
  • protected (受保護的)

Student 類:

#ifndef PROJECT5_STUDENT_H
#define PROJECT5_STUDENT_H

#include <string>
using namespace std;

class Student {
protected:
    int number;
    string name;
    char sex;
public:
    Student(int num, string n, char s);
    void show();
};

#endif //PROJECT5_STUDENT_H

Student.cpp:

#include <iostream>
#include "Student.h"
using namespace std;

Student::Student(int num, string n, char s) {
    number = num;
    name = n;
    sex = s;
}

void Student::show() {
    cout << "number: " << number << endl;
    cout << "name: " << name << endl;
    cout << "sex: " << sex << endl;
}

Student 派生類:

#ifndef PROJECT5_STUDENT1_H
#define PROJECT5_STUDENT1_H

#include "Student.h"

class Student1:public Student {
private:
    int age;
    string address;
public:
    Student1(int num, string n, char s, int a, string addr);
    void show1();
};

#endif //PROJECT5_STUDENT1_H

Student1.cpp:

#include <iostream>
#include "Student1.h"
using namespace std;

Student1::Student1(int num, string n, char s, int a, string addr) : Student(num, n, s) {
    Student(num, n, s);
    age = a;
    address = addr;
}

void Student1::show1() {
    show();
    cout << "age: " << age << endl;
    cout << "address: " << address << endl;
}

mian:

#include <iostream>
#include "Student1.h"

int main() {
    Student1 student1(1, "Little White", 'f', 18, "火星");
    student1.show1();

    return 0;
}

輸出結果:

number: 1
name: Little White
sex: f
age: 18
address: 火星

派生類中的成員包括從基類繼承過來的成員和自己增加的成員兩大部分. 每一部分佈分別包括數據成員和成員函數.

派生類的構造函數和析構函數

構造函數和析構函數:

構造函數的主要作用是對數據成員初始化析構函數在釋放對象前做一些相關的處理

因為派生類還繼承瞭基類的數據成員. 設計派生類的構造函數時, 不僅要考慮派生類所增加的數據成員的初始化, 還應當考慮基類的數據成員初始化. 於是我們在執行派生類的構造函數時, 調用基類的構造函數.

派生類構造函數一般形式

派生類構造函數名 (總形式參數表列) : 基類構造函數名 (實際參數表列) {
    派生類中新增數據成員初始化語句
}

類內定義

在類內定義派生類構造函數:

Student1::Student1(int num, string n, char s, int a, string addr) : Student(num, n, s), age(a), address(addr) {}

類外定義

在類的外面定義派生類構造函數:

類內:
Student1(int num, string n, char s, int a, string addr);

類外:
Student1::Student1(int num, string n, char s, int a, string addr) : Student(num, n, s) {
    Student(num, n, s);  // 基類
    age = a;
    address = addr;
}

構造函數和析構函數執行的順序

建立派生類對象時, 執行構造函數的順序:

  • 派生類構造函數先調用基類構造函數
  • 再執行派生類構造函數本身 (即派生類構造函數的函數體)

在派生類對象釋放時:

  • 先執行派生類析構函數 ~Derived()
  • 再執行其基類析構函數 ~Base()

Base 類:

#ifndef PROJECT5_BASE_H
#define PROJECT5_BASE_H

class Base {
protected:
    Base();
    ~Base();
};

#endif //PROJECT5_BASE_H

Base.cpp:

#include <iostream>
#include "Base.h"
using namespace std;

Base::Base() {
    cout << "基類構造" << endl;
}

Base::~Base() {
    cout << "基類析構" << endl;
}

Derived 類:

#ifndef PROJECT5_DERIVED_H
#define PROJECT5_DERIVED_H

#include "Base.h"
using namespace std;

class Derived: public Base{
public:
    Derived(char c);
    ~Derived();
};

#endif //PROJECT5_DERIVED_H

Derived.cpp:

#include <iostream>
#include "Derived.h"
using namespace std;

Derived::Derived(char c) {
    cout << "子類構造函數, 值:" << c << endl;
}

Derived::~Derived() {
    cout << "子類析構函數" << endl;
}

main:

#include <iostream>
#include "Derived.h"
using namespace std;

Derived::Derived(char c) {
    cout << "子類構造函數, 值:" << c << endl;
}

Derived::~Derived() {
    cout << "子類析構函數" << endl;
}

輸出結果:

基類構造
子類構造函數, 值:b
子類析構函數
基類析構

子對象派生

子對象 (sub object), 即對象中的對象. 類的數據成員是另一個類的對象.

Student1 類:

#ifndef PROJECT5_STUDENT1_H
#define PROJECT5_STUDENT1_H

#include "Student.h"

class Student1:public Student {
private:
    int age;
    string address;
    Student president;
public:
    Student1(int num, string n, char s, int p_num, string p_n, char p_s, int a, string addr);
    void show1();
};

#endif //PROJECT5_STUDENT1_H

Student1.cpp:

#include <iostream>
#include "Student1.h"
using namespace std;

Student1::Student1(int num, string n, char s, int p_num, string p_n, char p_s, int a, string addr) : Student(num, n, s), president(p_num, p_n, p_s) {
    age = a;
    address = addr;
}

void Student1::show1() {
    show();
    cout << "age: " << age << endl;
    cout << "address: " << address << endl;
    cout << "==========班長信息==========" << endl;
    president.show();
}

main:

#include <iostream>
#include "Student1.h"
using namespace std;

int main() {
    Student1 student1(1, "Little White", 'f', 2, "班長", 'm', 18, "火星");
    student1.show1();

    return 0;
}

輸出結果:

number: 1
name: Little White
sex: f
age: 18
address: 火星
==========班長信息==========
number: 2
name: 班長
sex: m

註意事項

  • 當不需要對派生類新增的成員函數進行任何初始化操作時, 派生類構造函數體可以為空
  • 基類沒有構造函數或構造函數參數為空, 在派生類構造函數中可不寫調用基類構造函數的語句, 盜用派生類構造函數時系統會自動調用基類的默認構造函數
  • 基類中定義瞭有參的構造函數, 派生類構造函數總必須寫出基類的構造函數及其參數
  • 基類中既定義無參數的構造函數,又重載瞭有參數的構造函數, 派生類構造函數中可以調用帶參的基類構造函數, 也可以不調用基類的構造函數

到此這篇關於C++中繼承(inheritance)詳解及其作用介紹的文章就介紹到這瞭,更多相關C++繼承內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: