C++類和對象進階 —— 與數據結構的結合

在這里插入圖片描述

在這里插入圖片描述
🎁個人主頁:工藤新一1

🔍系列專欄:C++面向對象(類和對象篇)

🌟心中的天空之城,終會照亮我前方的路

🎉歡迎大家點贊👍評論📝收藏?文章


文章目錄

    • @[toc]
  • C++類和對象(上)
    • 一、類的定義
      • 1.1類定義格式
      • 1.2兼容結構體
    • 二、實例化
      • 2.1實例化概念
      • 2.2對象大小
      • 2.3內存對齊
    • 三、this指針
      • 3.1常量指針與指針常量
      • 3.2面試真題
      • 3.3淺識寄存器 esp/ebp
    • 四、C++與C語言實現Stack對比

C++類和對象(上)

一、類的定義

1.1類定義格式

  • class 為定義類的關鍵字,以棧為例:Stack 為類的名字,{} 中為類的主體,注意類定義結束時后?分號不能省略。類體中內容稱為類的成員:類中的變量稱為類的屬性或成員變量;類中的函數稱為類的方法或者成員函數

  • 為了區分成員變量,?般習慣上成員變量會加?個特殊標識,如成員變量前?或者后?加 _ 或者 m 開頭,注意 C++ 中這個并不是強制的,只是?些慣例,具體看公司的要求

  • 定義在類中的成員函數默認為 inline(內聯)

#include<iostream>
using namespace std;
#include<cassert>typedef int STDataType;
class Stack
{
public://成員函數//1、對棧初始化void StackInit(int n = 4){array = (STDataType*)malloc(sizeof(STDataType) * n);if (array == nullptr){perror("malloc fail!");exit(1);}capacity = 4;top = 0;}//2、入棧操作void StackPush(STDataType x){//增容操作if (top == capacity){int newCapacity = capacity == 0 ? 4 : 2 * capacity;STDataRtpe* temp = (STDataType*)realloc(array, newCapacity * sizeof(STDataType));if (temp == nullptr){perror("realloc fail!");exit(1);}array = temp;capacity = newCapacity;}array[top++] = x;}//3、檢擦棧頂元素STDataRtpe StackTop(){assert(!StackEmpty());return array[top - 1];}//4、判空操作bool StackEmpty(){return top == 0;}//5、出棧操作void StackPop(){assert(!StackEmpty());/*斷言:條件為ture,程序繼續執行條件為false,程序停止運行*/top--;}//6、銷毀棧void StackDestroy(){if(array)free(array);array = nullptr;top = capacity = 0;}private://成員變量(多個變量的符合)STDataType* array;size_t capacity;size_t top;
};int main()
{Stack st;st.StackInit();return 0;
}

? 數據結構 ** 中的棧數據寫在 結構體中 ,棧操作實現方法在 結構體外,而在類中將數據(成員變量)與實現方法(成員函數)統一寫在類內**


1.2兼容結構體

  • C++struct 也可以定義類,C++ 兼容C中 struct 的?法,同時 struct 升級成了類,明顯的變化是 struct 中可以定義函數,?般情況下我們還是推薦? class 定義類
  • C++ 中,struct 的結構體成員默認持有公共權限 public,而 class 的成員對象默認持有私有權限 private

以鏈表為例:

/*C++ 將 struct 升級為了類1、結構體類中可以定義函數2、struct 名稱就可以代表數據類型
*///C++兼容 C 中 struct 的用法
typedef int LTDataType;typedef struct ListNodeC
{LTDataType val;struct ListNodeC* next;//不可以直接在結構體中 ListNodeC* next;}LTNode;//不需要 typedef 修飾,結構體名 ListNodeCPP 就是數據類型
struct ListNodeCPP
{//不僅可以定義變量,也可定義函數void LTInit(LTDataType x){val = x;next = nullptr;}private:LTDataType val;ListNodeCPP* next;
};int main()
{LTNode* node1 = NULL;struct ListNodeC* node2 = NULL;ListNodeCPP* node = nullptr;node->LTInit(1);return 0;
}

本質上:

  • 結構體是數據的集合
  • 類是數據和方法的集合

二、實例化

2.1實例化概念

  • ?類類型在物理內存中創建對象的過程,稱為類實例化出對象

  • 類是對象進行的?種抽象描述,是?個模型?樣的東西,限定了類有哪些成員變量,這些成員變量只 是聲明,沒有分配空間,?類實例化出對象時,才會分配空間

  • ?個類可以實例化出多個對象,實例化出的對象 占?實際的物理空間,存儲類成員變量。打個? ?:類實例化出對象就像現實中使?建筑設計圖建造出房?,類就像是設計圖,設計圖規劃了有多 少個房間,房間??功能等,但是并沒有實體的建筑存在,也不能住?,?設計圖修建出房?,房 ?才能住?。同樣類就像設計圖?樣,不能存儲數據,實例化出的對象分配物理內存存儲數據

在這里插入圖片描述


class Date
{
public:void Init(int year, int month, int day){this->year = year;this->month = month;this->day = day;}private://成員變量是類中的聲明(沒有開辟任何空間)int year;int month;int day;
};
int main()
{//通過類所實例化出的對象為成員變量開辟空間Date d1, d2;return 0;
}

2.2對象大小

  • 實例對象中,只存儲成員變量地址,不存儲成員函數地址

? 分析?下類對象中哪些成員呢?類實例化出的每個對象,都有獨?的數據空間,所以對象中肯定包含 成員變量,那么成員函數是否包含呢?

? ?先 函數被編譯后是?段指令,在實例對象中沒辦法存儲,這些指令 存儲在?個單獨的區域(代碼段),那么實例對象中?要存儲的話,只能通過 成員函數的指針

? 再分析?下,實例對象中是否有存儲指針的必要呢,Date 實例化 d1d2兩 個對象,d1d2 都有各?獨?的成員變量 year/_month/_day 存儲各?的數據,但是 d1d2 的成員函數 Init/Print 指針卻是?樣的,存儲在對象中就浪費了。

class Date
{
public:void Init(int year, int month, int day){this->year = year;this->month = month;this->day = day;}private://成員變量是類中的聲明(沒有開辟任何空間)int year;int month;int day;
};
int main()
{//通過類所實例化出的對象為成員變量開辟空間Date d1, d2;cout << sizeof(Date) << endl;cout << sizeof(d1) << endl;return 0;
}

? 在這里插入圖片描述

匯編角度:函數調用,被定義結束后是一串指令,這串指令會存儲到一個單獨的區域(常量區,在操作系統的角度上:也稱代碼段)


? 在這里插入圖片描述


? 成員變量需要獨立的空間存放各種來自外界傳入的值

C++//通過不同實例對象調用的 year 需要不同空間存儲獨立的值(本質:存儲地址不同)d1.year++;d2.year++;//成員函數 Print,所有對象共享同一份函數代碼,而非單獨存儲在某一個對象上d1.Print();d2.Print();

? 如果? Date 實例化100個對象,那么 成員函數指針 就重復存儲100次,太浪費了。這?需要再額外哆嗦?下,其實 函數指針 是不需要存儲的,函數指針是?個地址,調?函數被編譯成匯編指 令[call 地址],其實編譯器在編譯鏈接時,就要找到函數的地址,不是在運?時找, 只有動態多態是在運?時找,就需要存儲函數地址,這個我們以后會講解

  • 函數在本文件中有定義 - 編譯階段確定函數地址
  • 函數定義在外文件 - 鏈接階段確定函數

在這里插入圖片描述


上面我們分析了 實例對象只存儲成員變量C++ 規定類實例化的對象也要符合 **內存對齊 **的規則


2.3內存對齊

設計思路:以空間換時間,每個對象從對齊數的位置開始存放

  • 第?個成員在與結構體偏移量為 0 的地址處

  • 其他成員變量要對?到某個數字(對?數)的整數倍的地址處

  • 注意:對?數=編譯器默認的?個對?數與該成員??的較?值

  • VS中默認的對?數為 8

  • 結構體總??為:最?對?數(所有變量類型最?者與默認對?參數取最?)的整數倍

  • 如果嵌套了結構體的情況,嵌套的結構體對?到??的最?對?數的整數倍處,結構體的整體?? 就是所有最?對?數(含嵌套結構體的對?數)的整數倍


class A
{
public:void Print(){cout << _ch << endl;}
private:char _ch;int _i;
};
class B
{
public:void Print(){//...}
};
class C
{ };
int main()
{cout << sizeof(A) << endl;//8cout << sizeof(B) << endl;//1cout << sizeof(C) << endl;//1return 0;
}
  • 上?的程序運?后,我們看到沒有成員變量的B和C類對象的??是 1,為什么沒有成員變量還要給1個 字節呢?因為如果?個字節都不給,怎么表?對象存在過呢!所以這?給1字節,純粹是為了 占位標識 對象存在

面試經典問題:為什么需要內存對齊?

在這里插入圖片描述


在這里插入圖片描述


在這里插入圖片描述


三、this指針

  • Date 類中有 InitPrint 兩個成員函數,函數體中沒有關于不同對象的區分,那當 d1 調? InitPrint 函數時,該函數是如何知道應該訪問的是 d1 對象還是 d2 對象呢?那么這?就要看到 C++ 給了 ?個隱含的 this 指針解決這?的問題
  • C++ 規定不能在實參和 形參 的位置顯?的寫 this指針 (編譯時編譯器會處理),但是可以在函數體內顯 ?使? this指針
class Date
{
public:void Init(int year, int month, int day){this->year = year;this->month = month;this->day = day;}void Print(){cout << year << "/" << month << "/" << day << endl;}private:int year;int month;int day;
};
int main()
{Date d1, d2;d1.Init(2025, 5, 1);d2.Init(2025, 5, 2);d1.Print();d2.Print();return 0;
}

思考:d1、d2 調用的是同一個 Print,執行的是同一個函數,參數相同,那為什么輸出的值不同?

我們先前調用同一個函數,執行出的結果不同,是因為我們傳入了不同的參數

編譯階段,編譯器為我們處理隱藏過程。實際上,我們調用同一個函數 Print() 執行出了不同結果,還是因為我們傳入了不同參數

在這里插入圖片描述


同樣地,

在這里插入圖片描述

this 本身無法被修改:this = nullptr(false)


3.1常量指針與指針常量

  • 常量指針與指向常量的指針

在這里插入圖片描述


在這里插入圖片描述


在這里插入圖片描述


驗證 this 指針指向 d1/d2對象地址:
在這里插入圖片描述


3.2面試真題

在這里插入圖片描述


答案:

? 正常運行

在這里插入圖片描述

Print() 編譯時確定地址,不存在 對空指針進行解引用的行為


在這里插入圖片描述


對象 p 的作用:

  • 搜查、核對成員函數的出處
  • 指針所指向的對象(或對象)傳遞 this指針

在這里插入圖片描述


  • 編譯錯誤:語法問題,因此對于空指針的解引用(運行錯誤)一定不會觸及語法編譯的問題

  • 鏈接錯誤:語法規則符合,但存在函數或變量只聲明,未定義行為

  • 運行錯誤:行為/功能錯誤

在這里插入圖片描述


答案:

? 運行崩潰

在這里插入圖片描述

(*p).Print(); 同理


在這里插入圖片描述


解決方法:使 指針p 指向一個有效對象

C++A aa;A* p = &aa;//或 A* p = new A();

在這里插入圖片描述


? 常量區(語言層面) - 代碼段(或叫數據段 - 操作系統角度)(函數被編譯成指令后,存儲在常量區)

? 代碼段:將函數編譯好的代碼指令(因此代碼指令存儲在常量區/代碼段)

? this指針 所存放的區域中,this指針 存放在對象中這一選項或許會有些許疑慮,但很簡單,如果其存放在對象中,那么 sizoef(指針) == 4;這就與我們前面提到的 sizeof(p)(或sizeof(Person))== 1; 背道而馳了,因此,可論證: this指針 并不存儲在實例對象中


在這里插入圖片描述


this指針 是形式參數,嚴格一點是存儲在 棧和寄存器

3.3淺識寄存器 esp/ebp

在這里插入圖片描述


四、C++與C語言實現Stack對比

?向對象三?特性:封裝、繼承、多態,下?的對?我們可以初步了解?下封裝。 通過下?兩份代碼對?,我們發現 C++ 實現 Stack 形態上還是發?了挺多的變化,底層和邏輯上沒啥變化

以棧為例,C++ 對棧的各項操作進行了嚴格封裝(減少了 C語言 多樣化,但易錯誤的代碼形態),而 C語言 則更依賴于程序員應對形式多樣化代碼能力的素質

CSTack st;//訪問棧頂元素,方式一(直接調用函數 - 推薦):st.STop();//方式二:st.arr[st.top - 1];方式二:存在一定的不安全性,比如數組越界、0 - 1 == -1 等情況 

  • C++ 中數據和函數都放到了類??,通過 訪問限定符 進?了限制,不能再隨意通過對象直接修改數 據,這是 C++封裝 的?種體現,這個是最重要的變化。這?的 封裝 的本質是?種更嚴格規范的管理,避免出現亂訪問修改的問題 。當然 封裝 不僅僅是這樣的,我們后?還需要不斷的去學習

  • C++ 中有?些相對?便的語法,?如 Init 給的缺省參數會?便很多,成員函數每次不需要傳對象地址,因為 this指針 隱含的傳遞了,?便了很多,使?類型不再需要 typedef ?類名就很?便


在這里插入圖片描述

🌟 各位看官好我是工藤新一1呀~

🌈 愿各位心中所想,終有所致!

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

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

相關文章

Java中進階并發編程

第一章、并發編程的挑戰 并發和并行&#xff1a;指多線程或多進程 線程的本質&#xff1a;操作系統能夠進行運算調度的最小單位&#xff0c;是進程&#xff08;Process&#xff09;中的實際工作單元 進程的本質&#xff1a;操作系統進行資源分配和調度的基本單位&#xff0c…

《 指針變量類型與內存訪問:揭秘背后的奧秘》

&#x1f680;個人主頁&#xff1a;BabyZZの秘密日記 &#x1f4d6;收入專欄&#xff1a;C語言 &#x1f30d;文章目入 一、指針變量類型的基本概念二、指針類型與內存訪問字節數的關系&#xff08;一&#xff09;整型指針&#xff08;二&#xff09;字符型指針&#xff08;三&…

mapbox進階,使用mapbox-plugins插件加載餅狀圖

????? 主頁: gis分享者 ????? 感謝各位大佬 點贊?? 收藏? 留言?? 加關注?! ????? 收錄于專欄:mapbox 從入門到精通 文章目錄 一、??前言1.1 ??mapboxgl.Map 地圖對象1.1 ??mapboxgl.Map style屬性二、??使用mapbox-plugins插件加載餅狀圖1. ?…

GraphicLayer與BusineDataLayer層級控制

補充說明&#xff1a; 當參與層級控制的元素是點型元素時&#xff0c;是無法參與ZIndex層級控制的&#xff0c;此時可以換個解決方案 1.給不同的高度值實現&#xff0c;元素間的層級控制覆蓋 import * as mars3d from "mars3d"export let map // mars3d.Map三維地…

uniapp 百家云直播插件打包失敗

打包錯誤日志 Android自有證書 打包失敗 錯誤日志: https://app.liuyingyong.cn/build/errorLog/cf41a610-effe-11ef-88db-05262d4c3e5d原因&#xff1a;需要導入插件依賴 依賴地址&#xff1a;https://ext.dcloud.net.cn/plugin?id16289 百家云直播插件地址 直播插…

【C++】”如虎添翼“:模板初階

泛型編程&#xff1a; C中一種使用模板來實現代碼重用和類型安全的編程范式。它允許程序員編寫與數據類型無關的代碼&#xff0c;從而可以用相同的代碼邏輯處理不同的數據類型。模板是泛型編程的基礎 模板分為兩類&#xff1a; 函數模板&#xff1a;代表了一個函數家族&#x…

十五、多態與虛函數

十五、多態與虛函數 15.1 引言 面向對象編程的基本特征&#xff1a;數據抽象&#xff08;封裝&#xff09;、繼承、多態基于對象&#xff1a;我們創建類和對象&#xff0c;并向這些對象發送消息多態&#xff08;Polymorphism&#xff09;&#xff1a;指的是相同的接口、不同的…

點云特征提取的兩大經典范式:Voxel-based 與 Pillar-based

點云特征提取的兩大經典范式&#xff1a;Voxel-based 與 Pillar-based 在點云處理領域&#xff0c;尤其是針對 3D 目標檢測任務&#xff0c;特征提取是核心環節之一。目前&#xff0c;Voxel-based&#xff08;體素化&#xff09;和 Pillar-based&#xff08;柱狀化&#xff09…

前蘋果首席設計官回顧了其在蘋果的設計生涯、公司文化、標志性產品的背后故事

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

web 自動化之 selenium 元素四大操作三大切換等待

文章目錄 一、元素的四大操作二、三大切換&等待1、切換窗口:當定位的元素不在當前窗口&#xff0c;則需要切換窗口2、切換iframe&#xff1a;當定位的元素在frame/iframe&#xff0c;則需要切換3、切換彈出窗口 一、元素的四大操作 1、輸入 2、點擊 3、獲取文本 4、獲取屬…

window server 2012安裝sql server2008 r2

執行sql server2008 r2安裝目錄下的setup 選擇運行程序而不獲取幫助 然后就是讓人絕望的 只能先搞這個了&#xff0c;F*微軟&#xff0c;自家軟件不讓正常安裝 打開服務器管理器->添加角色和功能->選擇Web 服務&#xff08;IIS&#xff09;->添加.NET Framework3.5 然…

【K8S學習之生命周期鉤子】詳細了解 postStart 和 preStop 生命周期鉤子

0. 參考 Kubernetes容器生命周期 —— 鉤子函數詳解&#xff08;postStart、preStop&#xff09; - 人艱不拆_zmc - 博客園詳解Kubernetes Pod優雅退出 - 人艱不拆_zmc - 博客園 1. Kubernetes 生命周期鉤子概述 在 Kubernetes 中&#xff0c;生命周期鉤子&#xff08;Lifec…

測試文章標題01

模型上下文協議&#xff08;Model Context Protocol, MCP&#xff09;深度解析 一、MCP的核心概念 模型上下文協議&#xff08;Model Context Protocol, MCP&#xff09;是一種用于規范機器學習模型與外部環境交互的標準化框架。其核心目標是通過定義統一的接口和數據格式&am…

kubuntu系統詳解

Kubuntu 系統深度解析&#xff08;從系統架構到用戶體驗&#xff09; 一、定位與核心特性 Kubuntu 是 Ubuntu 的官方 KDE 衍生版&#xff0c;基于 Ubuntu 的穩定底層&#xff08;Debian 技術棧&#xff09;&#xff0c;搭載 KDE Plasma 桌面環境&#xff0c;主打 “功能豐富、…

cURL:通過URL傳輸數據的命令行工具庫介紹

文章目錄 1. 什么是 curl&#xff1f;2. 下載與安裝 curl3. curl 的常見用法3.1 獲取網頁內容3.2 下載文件3.3 發送 POST 請求&#xff08;帶表單數據&#xff09;3.4 發送帶 JSON 的 POST 請求 1. 什么是 curl&#xff1f; cURL&#xff08;CommandLine URL&#xff09;是非常…

從零搭建AI工作站:Gemma3大模型本地部署+WebUI配置全套方案

文章目錄 前言1. 安裝Ollama2.Gemma3模型安裝與運行3. 安裝Open WebUI圖形化界面3.1 Open WebUI安裝運行3.2 添加模型3.3 多模態測試 4. 安裝內網穿透工具5. 配置固定公網地址總結 前言 如今各家的AI大模型廝殺得如火如荼&#xff0c;每天都有新的突破。今天我要給大家安利一款…

Element Plus對話框(ElDialog)全面指南:打造靈活彈窗交互

&#x1f4cc; 開篇導語 對話框是Web應用中實現用戶交互的核心組件之一&#xff0c;常用于信息確認、表單提交或詳情展示。Element Plus的ElDialog組件以高擴展性和優雅動效著稱&#xff0c;支持高度定制化開發。本文將從基礎配置到進階技巧&#xff0c;手把手教你掌握對話框組…

解決WSL、Ubuntu的.ico圖標不正確顯示縮略圖

解決WSL、Ubuntu的.ico圖標不正確顯示縮略圖 問題描述 Win10系統中由于更新了某些軟件&#xff0c;篡改了默認的圖像顯示軟件&#xff0c;導致WSL等軟件未能成功顯示圖標&#xff0c;表現如下&#xff1a; 解決方法 將ico文件的默認打開方式更改為“畫圖”&#xff0c;如下…

[數據結構高階]并查集初識、手撕、可以解決哪類問題?

標題&#xff1a;[數據結構高階]并查集初識、手撕、可以解決哪類問題&#xff1f; 水墨不寫bug 文章目錄 一、認識并查集二、模擬實現并查集三、用并查集解決問題1、[省份的數量](https://leetcode.cn/problems/number-of-provinces/)2、[等式方程的可滿足性](https://leetcode…

如何快速入門大模型?

學習大模型的流程是什么 &#xff1f; 提示詞工程&#xff1a;只需掌握提問技巧即可使用大模型&#xff0c;通過優化提問方式獲得更精準的模型輸出套殼應用開發&#xff1a;在大模型生態上開發業務層產品&#xff08;如AI主播、AI小助手等&#xff09;&#xff0c;只需調用API…