C++對象繼承詳解:從入門到精通

繼承是面向對象編程的三大特性之一,也是C中實現代碼復用和多態的重要機制。本文將帶你深入理解C繼承的核心概念與應用。

一、繼承的基本概念

1.1 什么是繼承?

繼承允許我們基于已有的類創建新類,新類(派生類)可以繼承已有類(基類)的屬性和方法,并添加自己的特性。

繼承的優勢:

  • 代碼復用:避免重復編寫相同代碼

  • 擴展性:在現有類基礎上添加新功能

  • 層次結構:建立類之間的層次關系

1.2 繼承語法

class BaseClass {// 基類成員
};class DerivedClass : access-specifier BaseClass {// 派生類成員
};

訪問說明符:

  • public:基類的公有成員在派生類中保持公有

  • protected:基類的公有成員在派生類中變為保護

  • private:基類的公有和保護成員在派生類中變為私有(默認)

二、繼承類型詳解

2.1 公有繼承(public)

最常用的繼承方式,遵循"is-a"關系

class Animal {
public:void eat() { cout << "Eating..." << endl; }
protected:int age;
};class Dog : public Animal {
public:void bark() { eat();      // 可訪問基類public方法age = 2;    // 可訪問基類protected成員cout << "Woof!" << endl; }
};int main() {Dog myDog;myDog.eat();    // 輸出: Eating...myDog.bark();   // 輸出: Woof!
}

2.2 保護繼承(protected)

基類的公有和保護成員在派生類中都變為保護

class Vehicle {
public:void start() { cout << "Starting..." << endl; }
};class Car : protected Vehicle {
public:void drive() { start();  // 在派生類中可以訪問}
};int main() {Car myCar;// myCar.start(); // 錯誤! 在類外不可訪問myCar.drive();    // 正確
}

2.3 私有繼承(private)

基類的所有成員在派生類中都變為私有(默認繼承方式)

class Engine {
public:void ignite() { cout << "Igniting..." << endl; }
};class Car : private Engine { // private可省略
public:void start() { ignite();  // 在派生類中可以訪問}
};int main() {Car myCar;// myCar.ignite(); // 錯誤! 在類外不可訪問myCar.start();     // 正確
}

三、派生類的構造與析構

3.1 構造順序

  1. 基類構造函數

  2. 派生類的成員對象構造函數

  3. 派生類自身構造函數

3.2 析構順序

與構造順序相反:

  1. 派生類自身析構函數

  2. 派生類的成員對象析構函數

  3. 基類析構函數

class Base {
public:Base() { cout << "Base constructor" << endl; }~Base() { cout << "Base destructor" << endl; }
};class Derived : public Base {
public:Derived() : Base() { cout << "Derived constructor" << endl; }~Derived() { cout << "Derived destructor" << endl; }
};int main() {Derived d;/* 輸出:Base constructorDerived constructorDerived destructorBase destructor*/
}

四、函數重寫與多態性

4.1 虛函數(virtual)

使用virtual關鍵字聲明可在派生類中重寫的函數

class Shape {
public:virtual void draw() {cout << "Drawing a shape" << endl;}
};class Circle : public Shape {
public:void draw() override { // C++11引入override關鍵字cout << "Drawing a circle" << endl;}
};int main() {Shape* shape = new Circle();shape->draw(); // 輸出: Drawing a circledelete shape;
}

4.2 純虛函數與抽象類

包含純虛函數的類稱為抽象類,不能實例化

class Shape {
public:virtual void draw() = 0; // 純虛函數
};class Rectangle : public Shape {
public:void draw() override {cout << "Drawing a rectangle" << endl;}
};int main() {// Shape s; // 錯誤! 抽象類不能實例化Shape* shape = new Rectangle();shape->draw(); // 輸出: Drawing a rectangledelete shape;
}

五、多重繼承與虛繼承

5.1 多重繼承

一個類可以繼承多個基類

class Printer {
public:void print() { cout << "Printing..." << endl; }
};class Scanner {
public:void scan() { cout << "Scanning..." << endl; }
};class Copier : public Printer, public Scanner {
public:void copy() {print();scan();cout << "Copying completed!" << endl;}
};

5.2 菱形繼承問題

菱形繼承結構:

    Animal/   \/     \
Mammal   WingedAnimal\     /\   /Bat

問題描述:

當 Bat 類同時繼承 Mammal 和 WingedAnimal 時,如果它們都繼承自 Animal,會導致 Bat 對象中包含兩份 Animal 成員

class Animal {
public:int age;
};class Mammal : public Animal {};
class WingedAnimal : public Animal {};class Bat : public Mammal, public WingedAnimal {};int main() {Bat bat;// bat.age = 2; // 錯誤! 二義性訪問bat.Mammal::age = 2;     // 通過Mammal路徑訪問bat.WingedAnimal::age = 3; // 通過WingedAnimal路徑訪問cout << bat.Mammal::age << endl;     // 輸出: 2cout << bat.WingedAnimal::age << endl; // 輸出: 3
}

5.3 虛繼承解決方案

使用virtual關鍵字解決菱形繼承的二義性問題

class Animal {
public:int age;
};class Mammal : virtual public Animal {};
class WingedAnimal : virtual public Animal {};class Bat : public Mammal, public WingedAnimal {};int main() {Bat bat;bat.age = 2; // 沒有二義性// 未使用虛繼承時: bat.Mammal::age 和 bat.WingedAnimal::age
}

六、繼承中的訪問控制總結

基類成員訪問權限

繼承類型

在派生類中的訪問權限

public

public

public

protected

public

protected

private

public

不可訪問

public

protected

protected

protected

protected

protected

private

protected

不可訪問

public

private

private

protected

private

private

private

private

不可訪問

七、繼承的最佳實踐

  1. 遵循LSP原則:派生類應該能夠完全替代基類

  2. 優先使用組合:除非是"is-a"關系,否則優先使用組合而非繼承

  3. 避免深層次繼承:繼承層次不宜過深(通常不超過3層)

  4. 使用override關鍵字:明確表示重寫基類虛函數

  5. 基類析構函數聲明為虛函數:確保正確調用派生類析構函數

class Base {
public:virtual ~Base() {} // 虛析構函數
};

八、總結

C++繼承機制提供了強大的代碼復用和多態支持:

  • 三種繼承方式:public、protected、private

  • 虛函數實現運行時多態

  • 虛繼承解決菱形繼承問題

  • 抽象類定義接口規范

正確使用繼承可以使代碼更加靈活、可擴展,但需注意避免過度使用繼承帶來的設計問題。

掌握繼承機制是成為C++高級開發者的必經之路。希望本文能幫助你建立清晰的繼承概念體系,在實際開發中靈活運用這些知識!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/910624.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/910624.shtml
英文地址,請注明出處:http://en.pswp.cn/news/910624.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Jenkins安裝與配置全攻略:從入門到高級功能實戰

在DevOps實踐中,Jenkins作為最流行的持續集成工具之一,扮演著至關重要的角色。本文將全面介紹Jenkins的安裝、配置及高級功能使用,幫助開發、運維和測試團隊快速搭建高效的CI/CD流水線。 一、Jenkins安裝 1.1 環境準備 Jenkins官網:https://jenkins.io 注意:Jenkins 2…

[OS_26] 計算機系統安全 | CIA原則 | 側信道攻擊

系統調用是唯一訪問操作系統對象的途徑 拒絕越權訪問 →→ Confidentiality拒絕越權修改 →→ Integrity(再加上公平資源調度 →→ Availability) 在操作系統 API 上&#xff0c;我們可以構建命令行工具、編譯器、數據庫、瀏覽器等豐富的應用。 當越來越多用戶開始共享計算機、…

Chromium 136 編譯指南 macOS篇:編譯優化技巧(六)

1. 引言 在現代軟件開發的高效化進程中&#xff0c;編譯優化已經從簡單的性能調優發展為一門綜合性的工程科學。對于Chromium 136這樣一個包含超過2500萬行代碼的超大規模項目而言&#xff0c;編譯時間往往成為制約開發效率的關鍵瓶頸。在典型的開發場景中&#xff0c;一次完整…

Spark教程6:Spark 底層執行原理詳解

文章目錄 一、整體架構概述二、核心組件詳解1. SparkContext2. DAG Scheduler3. Task Scheduler4. Executor 三、作業執行流程1. DAG 生成與 Stage 劃分2. Task 調度與執行3. 內存管理 四、Shuffle 機制詳解1. Shuffle 過程2. Shuffle 優化 五、內存管理機制1. 統一內存管理&am…

xlsx-style 插件批量導出多個sheet表格excel中遇到的問題及解決

Vue2中 前端界面導出表格&#xff0c;使用XLSXS插件版本(^0.8.13)導出表格存在表格背景顏色無法正常展示&#xff0c;百分比數據沒有正常展示 【有條件的盡量先升級高版本插件&#xff0c;此插件版本對樣式支持度不夠】 優先考慮插件版本升級 同樣的使用方法在vue3中沒有出現錯…

Java后端與Vue前端項目部署全流程:從環境配置到Nginx反向代理

文章目錄 1. 準備項目所需的環境2. 后端項目打包步驟 1&#xff1a;使用 Maven 打包步驟 2&#xff1a;定位生成的 JAR 包步驟 3&#xff1a;上傳 JAR 包到 Linux 系統步驟 4&#xff1a;驗證 Java 環境步驟 5&#xff1a;啟動 JAR 包 3. 前端項目打包步驟 1&#xff1a;執行 B…

Mybatis踩坑之一天

background: 對接AML系統&#xff0c;日間實時需要送交易對手要素過去&#xff08;目前主要是交易對手全名&#xff09;&#xff0c;夜間需要將歷史交易送AML進行回溯&#xff0c;交互方式是文件。文件要素為日期、對手類型、對手名、交易流水之類。 設置對送AML的文件設計表…

【PyTorch】分布式訓練報錯記錄-ERROR:torch.distributed.elastic.multiprocessing.api:failed (exitcode: 1)

最近&#xff0c;我在服務器上起基于PyTorch分布式框架的預訓練實驗&#xff0c;起初實驗都在順利進行&#xff0c;但是當我們把模型的深度與寬度調大之后&#xff0c;模型在訓練幾代之后便會出現如下的報錯&#xff1a; WARNING:torch.distributed.elastic.multiprocessing.a…

有哪些詞編碼模型

有哪些詞編碼模型 詞編碼模型:是將自然語言符號映射為稠密的高維向量,使語義相近的詞匯在向量空間中位置接近。 不過,也有部分模型會考慮字母或字符信息,如基于字節對編碼(BPE)的模型會將單詞拆分成子詞,這里的子詞可能是字母組合。 詞編碼模型的原理主要是通過機器學…

Mono 功能介紹與使用示例

Mono 功能介紹與使用示例 一、核心概念與特性 Mono 是 Spring Reactor 框架中的核心組件&#xff0c;屬于響應式編程&#xff08;Reactive Programming&#xff09;模型&#xff0c;專注于處理包含 0 或 1 個元素 的異步序列[1][2][5]。其核心特點包括&#xff1a; 異步非阻…

5060Ti雙顯卡+LLaMA-factory大模型微調環境搭建

查看環境確定安裝版本安裝CUDA12.8安裝Anaconda安裝Visual Studio C桌面開發環境&#xff08;編譯llama.cpp需要&#xff09;安裝cmake(編譯llama.cpp需要)安裝llama.cpp(用于量化)安裝huggingface-cli安裝llama-factory安裝PyTorch2.7.0安裝bitsandbytes安裝flash-attention加…

Lnmp和XunRuiCMS一鍵部署(Rocky linux)

先上傳XunRuiCMS-Study.zip包到當前目錄&#xff0c;可以去官網下載 #!/bin/bash # function: install nginx mysql php on Rocky Linux 9.5 with fixed PHP-FPM configip$(hostname -I | awk {print $1}) yhxunrui passwordxunrui123# 檢查是否為root用戶 if [ "$USER&qu…

高精度OFDR設備在CPO交換機中的應用

光電共封裝&#xff08;CPO&#xff09;交換機的特點 核心需求&#xff1a;CPO將光模塊與交換芯片集成封裝&#xff0c;縮短電互連距離&#xff0c;降低功耗和延遲&#xff0c;但需解決以下挑戰&#xff1a; 1.光器件微型化&#xff1a;硅光芯片、光纖陣列等需高精度制造。 …

Vulkan 通過 CMake 集成 Dear ImGUI

一、 目錄與文件部署 從官網獲取 IMGUI 代碼庫&#xff0c;在項目 extern 目錄下新建 imgui 目錄&#xff0c;將相關文件復制進去&#xff0c;構建出如下目錄結構&#xff1a; . ├── build ├── extern │ ├── glfw │ ├── glm │ └── imgui │ ├…

Linux設備框架:kset與kobject基本介紹

系列文章目錄 Linux設備框架&#xff1a;kset與kobject基本介紹 [link] Linux設備框架&#xff1a;kset與kobject源碼分析 [link] kset與kobject基本介紹 一、前言二、kobject、kset和設備的關系2.1 kset 結構體2.2 kobject 結構體 三、總結 一、前言 Linux 設備模型如同一座擁…

【AI論文】擴展大型語言模型(LLM)智能體在測試時的計算量

摘要&#xff1a;擴展測試時的計算量在提升大型語言模型&#xff08;LLMs&#xff09;的推理能力方面已展現出顯著成效。在本研究中&#xff0c;我們首次系統地探索了將測試時擴展方法應用于語言智能體&#xff0c;并研究了該方法在多大程度上能提高其有效性。具體而言&#xf…

LeapMotion-PhysicalHandsManager 類詳解

PhysicalHandsManager 類詳解 這個類是 Ultraleap 物理手交互系統的核心管理器,負責處理手部物理交互的不同模式。下面我將詳細解析這個類的結構和功能: 類概述 PhysicalHandsManager 繼承自 LeapProvider,是物理手交互系統的中央控制器: public class PhysicalHandsMa…

vue-22(理解組合式 API:setup、ref、reactive)

Vue.js 中的組合式 API 代表了我們構建和組織組件方式的重大轉變。它為傳統的選項式 API 提供了一種更靈活、更強大的替代方案&#xff0c;尤其適用于復雜的應用程序。本章將深入探討組合式 API 的核心概念&#xff1a;setup函數、ref和reactive&#xff0c;為你構建更可維護、…

【Golang玩轉MCP】-實現一個加減乘除MCP服務

文章目錄 概要1 首先創建一個MCP服務器2 添加MCP工具如何測試我們的MCP服務功能是否正常呢小結 概要 今天我們使用golang簡單實現一個加減乘除MCP服務 1 首先創建一個MCP服務器 s : server.NewMCPServer("Hello World Server","1.0.0",server.WithToolCa…

計算機網絡期末 網絡基礎概述

目錄 網絡的定義歷史發展(了解) 網絡的分類&#xff0c;功能和應用(熟悉) 網絡的組成與結構(理解) 網絡的 OSI 七層參考模型(熟悉) 網絡的 TCP/IP 四次模型(理解) 網絡有關性能指標(掌握) 網絡的定義歷史發展(了解) 計算機網絡是什么 四個階段 總結 網絡 互連網 因特網的…