【C++庖丁解牛】類與對象


📙 作者簡介 :RO-BERRY
📗 學習方向:致力于C、C++、數據結構、TCP/IP、數據庫等等一系列知識
📒 日后方向 : 偏向于CPP開發以及大數據方向,歡迎各位關注,謝謝各位的支持


請添加圖片描述


目錄

  • 1.面向過程和面向對象初步認識
  • 2.類的引入
  • 3.類的定義
  • 4.類的訪問限定符及封裝
    • 4.1 訪問限定符
    • 4.2 封裝
  • 5.類的作用域
  • 6.類的實例化
  • 7.類對象模型
    • 7.1 如何計算類對象的大小
    • 7.2 類對象的存儲方式
    • 7.3 結構體內存對齊規則
  • 8.this指針
    • 8.1 this指針的引出
    • 8.2 this指針的特性


1.面向過程和面向對象初步認識

  • C語言是面向過程的,關注的是過程,分析出求解問題的步驟,通過函數調用逐步解決問題。
    在這里插入圖片描述

在C語言里對于洗衣服就會分成一個一個過程
在這里插入圖片描述

  • C++是基于面向對象的,關注的是對象,將一件事情拆分成不同的對象,靠對象之間的交互完成。

在這里插入圖片描述
在這里插入圖片描述

2.類的引入

C語言結構體中只能定義變量,在C++中,結構體內不僅可以定義變量,也可以定義函數。比如:

之前在數據結構初階中,用C語言方式實現的棧,結構體中只能定義變量;現在以C++方式實現,會發現struct中也可以定義函數

C語言實現棧的代碼:

typedef int DataType;
struct Stack
{void Init(size_t capacity){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (nullptr == _array){perror("malloc申請空間失敗");return;}_capacity = capacity;_size = 0;}void Push(const DataType& data){// 擴容_array[_size] = data;++_size;}DataType Top(){return _array[_size - 1];}void Destroy(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}DataType* _array;size_t _capacity;size_t _size;
};
int main()
{Stack s;s.Init(10);s.Push(1);s.Push(2);s.Push(3);cout << s.Top() << endl;s.Destroy();return 0;
}

C++里面兼容C語言struct的所有用法
但是在C++中更喜歡用class來代替,這叫做類

3.類的定義

class className
{// 類體:由成員函數和成員變量組成
};  // 一定要注意后面的分號

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

類的兩種定義方式:

  1. 聲明和定義全部放在類體中,需注意:成員函數如果在類中定義,編譯器可能會將其當成內聯函數處理。

在這里插入圖片描述
2. 類聲明放在.h文件中,成員函數定義放在.cpp文件中,注意:成員函數名前需要加類名::
在這里插入圖片描述

一般情況下,更期望采用第二種方式。

成員變量命名規則的建議:

我們看看這個函數,是不是很僵硬?

class Date
{
public:void Init(int year){// 這里的year到底是成員變量,還是函數形參?year = year;}
private:int year;
};

所以一般都建議這樣

class Date
{
public:void Init(int year){_year = year;}
private:int _year;
};

或者這樣

class Date
{
public:void Init(int year){mYear = year;}
private:int mYear;
};

其他方式也可以的,主要看公司要求。一般都是加個前綴或者后綴標識區分就行

4.類的訪問限定符及封裝

4.1 訪問限定符

C++實現封裝的方式:用類將對象的屬性與方法結合在一塊,讓對象更加完善,通過訪問權限選
擇性的將其接口提供給外部的用戶使用

在這里插入圖片描述
我們先來看一看類的工作方式:

#include<iostream>
using namespace std;
class Date
{
private:int _day;int _month;int _year;
public:void Init(int day,int month,int year){_day=day;_month=month;_year=year;	}
}

關鍵字private和 public是新的,它們描述了對類成員的訪問控制。使用類對象的程序都可以直接訪問公有部分,但只能通過公有成員函數(或友元函數)來訪問對象的私有成員。
例如:要修改 Date 類的 day 成員,只能通過 Date 的成員函數。因此,公有成員函數是程序和對象的私有成員之間的橋梁,提供了對象和程序之間的接口。防止程序直接訪問數據被稱為數據隱藏(C++還提供了第三個訪問控制關鍵字protected,介紹類繼承時將討論該關鍵字。)

類設計盡可能將公有接口與實現細節分開。公有接口表示設計的抽象組件。將實現細節放在一起并將它們與抽象分開被稱為封裝。數據隱藏(將數據放在類的私有部分中)是一種封裝,將實現的細節隱藏在私有部分中。封裝的另一個例子是,將類函數定義和類聲明放在不同的文件中。下面我們會具體介紹封裝

【訪問限定符說明】

  1. public修飾的成員在類外可以直接被訪問
  2. protected和private修飾的成員在類外不能直接被訪問(此處protected和private是類似的)
  3. 訪問權限作用域從該訪問限定符出現的位置開始直到下一個訪問限定符出現時為止
  4. 如果后面沒有訪問限定符,作用域就到 } 即類結束。
  5. class的默認訪問權限為private,struct為public(因為struct要兼容C)

注意:訪問限定符只在編譯時有用,當數據映射到內存后,沒有任何訪問限定符上的區別

【面試題】
C++中struct和class的區別是什么?

C++需要兼容C語言,所以C++中struct可以當成結構體使用。另外C++中struct還可以用來
定義類。和class定義類是一樣的,區別是struct定義的類默認訪問權限是public,class定義的類
默認訪問權限是private。注意:在繼承和模板參數列表位置,struct和class也有區別,后序給大
家介紹。

4.2 封裝

【面試題】
面向對象的三大特性:封裝、繼承、多態。
在類和對象階段,主要是研究類的封裝特性,那什么是封裝呢?

封裝:將數據和操作數據的方法進行有機結合,隱藏對象的屬性和實現細節,僅對外公開接口來和對象進行交互。

**封裝本質上是一種管理,讓用戶更方便使用類。**比如:對于電腦這樣一個復雜的設備,提供給用戶的就只有開關機鍵、通過鍵盤輸入,顯示器,USB插孔等,讓用戶和計算機進行交互,完成日常事務。但實際上電腦真正工作的卻是CPU、顯卡、內存等一些硬件元件。

在這里插入圖片描述

對于計算機使用者而言,不用關心內部核心部件,比如主板上線路是如何布局的,CPU內部是如何設計的等,用戶只需要知道,怎么開機、怎么通過鍵盤和鼠標與計算機進行交互即可。因此計算機廠商在出廠時,在外部套上殼子,將內部實現細節隱藏起來,僅僅對外提供開關機、鼠標以及鍵盤插孔等,讓用戶可以與計算機進行交互即可。

在C++語言中實現封裝,可以通過類將數據以及操作數據的方法進行有機結合,通過訪問權限來
隱藏對象內部實現細節,控制哪些方法可以在類外部直接被使用。

5.類的作用域

類定義了一個新的作用域,類的所有成員都在類的作用域中。在類體外定義成員時,需要使用 ::
作用域操作符指明成員屬于哪個類域。

在類中定義的名稱(如類數據成員名和類成員函數名)的作用域都為整個類,作用域為整個類的名稱只在改類中是已知的,在類外時不可知的。因此,可以在不同類中使用相同的類成員名而不會引起沖突。另外,類作用域意味著不能從外部直接訪問到類的成員,共有成員函數也是如此,也就是說,要調用公有成員函數,必須通過對象:

Date A;   //創建類
Date.Init(2,4,2024); //調用類內部公有函數
Init(2,4,2024);    //錯誤用法,查無此函數

同樣在類外定義成員函數時,必須使用作用域解析運算符:

void Date::show()  //兩個連續冒號即是域解析運算符,前面跟上類的名稱即可
{...
}

使用類成員(類成員變量、類成員函數)時,必須根據上下文使用直接成員運算符(.)、間接成員運算符(->)或作用域解析運算符(::)

6.類的實例化

用類類型創建對象的過程,稱為類的實例化

  1. 類是對對象進行描述的,是一個模型一樣的東西,限定了類有哪些成員,定義出一個類并沒有分配實際的內存空間來存儲它;比如:入學時填寫的學生信息表,表格就可以看成是一個類,來描述具體學生信息。類就像謎語一樣,對謎底來進行描述,謎底就是謎語的一個實例。謎語:“年紀不大,胡子一把,主人來了,就喊媽媽” 謎底:山羊
  2. 一個類可以實例化出多個對象,實例化出的對象會占用實際的物理空間,存儲類成員變量
int main()
{Person._age = 100;   // 編譯失敗:error C2059: 語法錯誤:“.”return 0;
}

Person類是沒有空間的,只有Person類實例化出的對象才有具體的年齡

int main()
{Person A;      //實例化對象A._age = 100;    //運行成功return 0;
}
  1. 做個比方。類實例化出對象就像現實中使用建筑設計圖建造出房子,類就像是設計圖,只設
    計出需要什么東西,但是并沒有實體的建筑存在,同樣類也只是一個設計,實例化出的對象
    才能實際存儲數據,占用物理空間
    在這里插入圖片描述
    在這里插入圖片描述

7.類對象模型

7.1 如何計算類對象的大小

類的內存大小是多少呢?
我們前面學習過結構體的內存對齊規則,但是那是c語言
而C++又基本包含C語言的知識
那么C++類的大小是多少呢?

在這里插入圖片描述

在這里a的大小是多少呢?
Init成員函數指針在不在內存大小里面呢?

在這里插入圖片描述

結論是成員函數不在里面,類的大小只考慮成員對象的大小空間,成員函數不算成員對象。
那么成員函數為什么不在成員對象里面呢?

在這里插入圖片描述
我們想調用函數是需要調用地址的
這里兩個不同類對象的Init函數所調用的地址是不是一樣的呢?
答案是一樣的

7.2 類對象的存儲方式

存儲方式如下圖:

在這里插入圖片描述
類的成員對象是相互獨立的,但是對于一個類的成員函數它是放在一個公共區域的,就相當于一個小區,有很多戶人家,也就是實例化了很多個對象,但是在這個小區里籃球場,廣場只有一個,也就是公共區域,每家每戶都可以隨意使用。
在這里也就是我們可以每個實例化對象都可以訪問這個成員函數,但是這個成員函數是只初始化一次的,也就是放在公共區域,所以每一個類的實例化對象所計算內存大小只會計算成員對象,不會去計算成員函數,成員對象的內存計算就是該類中”成員變量”之和,當然要注意內存對齊

  • 但是這對于空類卻不一樣
    在這里插入圖片描述
    運行結果:
    在這里插入圖片描述

無成員變量的類,對象大小開一個字節,這個字節不存儲有效數據
標識定義的對象存在過

結論:

一個類的大小,實際就是該類中”成員變量”之和,當然要注意內存對齊
注意空類的大小,空類比較特殊,編譯器給了空類一個字節來唯一標識這個類的對象。

7.3 結構體內存對齊規則

  1. 第一個成員在與結構體偏移量為0的地址處。
  2. 其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。
    注意:對齊數 = 編譯器默認的一個對齊數 與 該成員大小的較小值。
    VS中默認的對齊數為8
  3. 結構體總大小為:最大對齊數(所有變量類型最大者與默認對齊參數取最小)的整數倍。
  4. 如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整
    體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。

8.this指針

8.1 this指針的引出

我們先來定義一個日期類 Date

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;    // 年int _month;  // 月int _day;     // 日
};
int main()
{Date d1, d2;d1.Init(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}

運行結果:
在這里插入圖片描述

對于上述類,有這樣的一個問題:
Date類中有 Init 與 Print 兩個成員函數,函數體中沒有關于不同對象的區分,那當d1調用 Init 函
數時,該函數是如何知道應該設置d1對象,而不是設置d2對象呢?

C++中通過引入this指針解決該問題,即:C++編譯器給每個“非靜態的成員函數“增加了一個隱藏
的指針參數,讓該指針指向當前對象(函數運行時調用該函數的對象),在函數體中所有“成員變量”
的操作,都是通過該指針去訪問。只不過所有的操作對用戶是透明的,即用戶不需要來傳遞,編
譯器自動完成。

所以,系統會將如上代碼改成下面的這樣:其中有函數參數Date *this

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(Date *this){cout << this->_year << "-" <<this->_month << "-" << this->_day << endl;}
private:int _year;    // 年int _month;  // 月int _day;     // 日
};
int main()
{Date d1, d2;d1.Init(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print(&d1);d2.Print(&d2);return 0;
}

注意:
我們是不能顯示的寫this參數的

8.2 this指針的特性

  1. this指針的類型:類類型* const,即成員函數中,不能給this指針賦值。
  2. 只能在“成員函數”的內部使用
  3. this指針本質上是“成員函數”的形參,當對象調用成員函數時,將對象地址作為實參傳遞給this形參。所以對象中不存儲this指針。
  4. this指針是“成員函數”第一個隱含的指針形參,一般情況由編譯器通過ecx寄存器自動傳遞,不需要用戶傳遞

在這里插入圖片描述
【面試題】

  1. this指針存在哪里?

this指針是形參,是存在棧幀上面的,會被系統回收銷毀的,在vs里面this存在寄存器里

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

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

相關文章

對單例模式的餓漢式、懶漢式的思考

目錄 1 什么是單例模式&#xff1f;1.1 什么是餓漢式&#xff1f;1.2 什么是懶漢式&#xff1f; 2 我對餓漢式的思考3 懶漢式3.1 解決懶漢式的線程安全問題3.1.1 加鎖&#xff1a;synchronized&#xff08;synchronized修飾靜態方法&#xff09;3.1.2 對“3.1.1”性能的改進 1 …

環形鏈表詳解(讓你徹底理解環形鏈表)

文章目錄 一.什么是環形鏈表&#xff1f;二.環形鏈表的例題&#xff08;力扣&#xff09; 三.環形鏈表的延伸問題 補充 一.什么是環形鏈表&#xff1f; 環形鏈表是一種特殊類型的鏈表數據結構&#xff0c;其最后一個節點的"下一個"指針指向鏈表中的某個節點&#xff…

Python 教學平臺,支持“多班教學”的課程授課方式|ModelWhale 版本更新

龍行龘龘、前程朤朤&#xff0c;ModelWhale 新一輪的版本更新&#xff0c;期待為大家帶來更優質的使用體驗。 本次更新中&#xff0c;ModelWhale 主要進行了以下功能迭代&#xff1a; 新增 課程&#xff08;包括課件、作業、算力&#xff09;按班級管理&#xff08;團隊版? …

springcloud的搭建和封裝,已進行開源,相互學習代碼知識。

springcloud架構的統一父工程&#xff0c;&#xff08;管理子模塊&#xff0c;管理依賴插件&#xff0c;依賴版本等&#xff09; abillty:能力服務塊&#xff1a;存放一些非業務相關的微服務&#xff0c;比如網關&#xff0c;身份認證等 exce: 網關中的一些異常信息處理 gatewa…

基于Springboot的人事管理系統 (有報告)。Javaee項目,springboot項目。

演示視頻&#xff1a; 基于Springboot的人事管理系統 &#xff08;有報告&#xff09;。Javaee項目&#xff0c;springboot項目。 項目介紹&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三層體系結構&am…

【Git】merge時報錯:refusing to merge unrelated histories

文章目錄 一、問題二、解決辦法1、將feature分支的東西追加到master分支中2、將feature里的東西直接覆蓋到master分支中 一、問題 今天將feature分支合并到master時報錯&#xff1a;refusing to merge unrelated histories&#xff08;拒絕合并無關歷史&#xff09; 報錯原因&…

一篇文章速通static關鍵字(JAVA)

目錄 1.原理——內存機制 1.1 修飾對象 1.2 lifecycle生命周期 2. 靜態屬性&#xff08;類屬性&#xff09;和實例屬性&#xff08;對象屬性&#xff09; 2.1 定義方式 2.2 調用方法 3. 靜態方法和屬性 3.1 在同一個類中 3.2 在不同類中 4.總結&#xff08;關鍵&#x…

SQLSyntaxEProrException異常產生原因及解決方案

java.sq1.SQLSyntaxEProrException異常產生原因及解決方案 01 異常的發生場景 在我mybatis-plus寫了一個查詢接口后出現的問題 java.sq1.SQLSyntaxEProrException日志報錯的意思是sql語法問題 02 異常的產生及其原因 我最開始又認為是MySQL數據庫表設計的問題&#xff0c…

ROS2從入門到精通:理論與實戰

ROS是什么&#xff1f; 隨著人工智能技術的飛速發展與進步&#xff0c;機器人的智能化已經成為現代機器人發展的終極目標。機器人發展的速度在不斷提升&#xff0c;應用范圍也在不斷拓展&#xff0c;例如自動駕駛、移動機器人、操作機器人、信息機器人等。機器人系統是很多復雜…

外貿福利 PHP源碼 WhatsApp 營銷 - 批量發件人、聊天、機器人、SaaS 搭建

WhatsApp 營銷工具對于外貿人員來說至關重要。隨著全球貿易的不斷發展&#xff0c;WhatsApp已成為了許多國際貿易商之間溝通的首選工具之一。通過利用WhatsApp營銷工具&#xff0c;外貿人員可以輕松地與客戶建立聯系&#xff0c;傳遞產品信息&#xff0c;進行價格談判&#xff…

Revit-二開之東西南北立面FilledRegion的CurveLoop計算-(4)

東西南北FilledRegion的CurveLoop計算 上一篇以東立面視圖為例創建FilledRegion,接下來我們將立面視圖創建FilledRegion的CurveLoop匯總一下。 上圖是對四個立面坐標系間的繪制方便我們計算FilledRegion的CurveLoop。 東立面CurveLoop計算 private CurveLoop GetEastCurveL…

3.1網安學習第三階段第一周回顧(個人學習記錄使用)

本周重點 ①HTML/JavaScript/CSS ②PHP ③正則表達式/文件上傳/文件讀寫 ④AJAX不跳轉提交 ⑤ OOP面向對象編程 本周主要內容 DAY1 HTML/JavaScript/CSS ①HTML 一、基本結構 <HTML> <head> //頭部內容 <title>網頁標題</title> </head&…

內網滲透-DC-9靶機滲透

攻擊機&#xff1a;kali 192.168.236.137 目標機&#xff1a;dc-9 192.168.236.138 一、信息收集 1.使用arp-scan -l和nmap進行主機發現和端口信息收集 nmap -sS -T5 --min-rate 10000 192.168.236.138 -sC -p- 發現22端口被阻塞 2.whatweb收集一下cms指紋信息 what http…

Vue開發實例(七)Axios的安裝與使用

說明&#xff1a; 如果只是在前端&#xff0c;axios常常需要結合mockjs使用&#xff0c;如果是前后端分離&#xff0c;就需要調用對應的接口&#xff0c;獲取參數&#xff0c;傳遞參數&#xff1b;由于此文章只涉及前端&#xff0c;所以我們需要結合mockjs使用&#xff1b;由于…

《熱辣滾燙》:用堅持不懈開啟逆境中的職場出路

"你只活一次&#xff0c;所以被嘲笑也沒有關系&#xff0c;想哭也沒有關系&#xff0c;失敗更沒有關系。" “人生就像一場拳擊賽&#xff0c;你站不起來&#xff0c;就永遠不知道自己有多強” “命運只負責洗牌&#xff0c;出牌的永遠是自己。” 在今年的賀歲檔電影市…

云時代【6】—— 鏡像 與 容器

云時代【6】—— 鏡像 與 容器 四、Docker&#xff08;三&#xff09;鏡像 與 容器1. 鏡像&#xff08;1&#xff09;定義&#xff08;2&#xff09;相關指令&#xff08;3&#xff09;實戰演習鏡像容器基本操作離線遷移鏡像鏡像的壓縮與共享 2. 容器&#xff08;1&#xff09;…

為什么模電這么難學?這是我見過最好的回答

大家好&#xff0c;我是磚一&#xff0c;有很多人抱怨模電難學&#xff0c;被譽為電子信息掛科率最高之一&#xff0c;下面聽我分析一下為啥模電這么難學&#xff1f; 01 理科的抽象思維 在高等教育體系中&#xff0c;模電是涉及半導體方向的第一門工程類課程&#xff0c;是一…

2024年3月5-7日年生物發酵裝備展-環科環保科技

參展企業介紹 山東環科環保科技有限公司,是一家集環保設備的設計、制造、安裝、服務及環境治理工程總承包于一體的企業。 公司長期專注于大氣、水、危固廢三大領域&#xff0c;以科技創造碧水藍天&#xff0c;為客戶提供環保解決方案。 以穩定的產品及服務質量、適用的技術、…

【環境搭建】linux centos7安裝mosquitto消息代理軟件操作步驟以及遇到問題日常記錄

最近需要用到mqtt&#xff0c; 選擇安裝mosquitto。由于安裝mosquitto花了我一點時間&#xff0c;簡單記錄下。安裝環境是linux centos7&#xff0c; 其他像windows、mac或者ubuntu 參考下 https://mosquitto.org/download/ 英文官網&#xff0c;或者別人寫的文章。 服務器…

微型世界:嵌入式科技的無限可能

微型世界&#xff1a;嵌入式科技的無限可能 1. 嵌入式科技的定義與特點 定義&#xff1a;嵌入式科技是一種特殊的計算機系統&#xff0c;通常用于特定的應用領域&#xff0c;如智能手機、智能家居設備等。特點&#xff1a;小巧、低功耗、高效率、實時性強、可靠性高、成本較低…