【C++】2. 類和對象(上)

文章目錄

  • 一、類的定義
    • 1、類定義格式
    • 2、訪問限定符
    • 3、類域
  • 二、實例化
    • 1、實例化概念
    • 2、對象??
  • 三、this指針
  • 四、C++和C語?實現Stack對?

一、類的定義

1、類定義格式

  • class為定義類的關鍵字,Stack為類的名字,{ }中為類的主體,注意類定義結束時后?分號不能省略。類體中內容稱為類的成員,類中的變量稱為類的屬性或成員變量類中的函數稱為類的?法或者成員函數
#include<iostream>
using namespace std;class Stack
{
public://成員函數void Push(int x){}void Pop(){}int Top(){return 0;}private://成員變量int* a;int top;int capacity;};int main()
{Stack st;st.Push(1);st.Pop();return 0;
}
  • 為了區分成員變量,?般習慣上成員變量會加?個特殊標識,如成員變量前?或者后?加_或者 m開頭,注意C++中這個并不是強制的,只是?些慣例。

  • C++中struct也可以定義類,C++兼容C中struct的?法,同時struct升級成了類,明顯的變化是struct中可以定義函數,?般情況下我們還是推薦?class定義類。

#include<iostream>
using namespace std;struct Date
{
public:void Init(int year, int month, int day);private://用_標識成員變量  聲明int _year;int _month;int _day;
};void Date::Init(int year, int month, int day)
{_year = year;_month = month;_day = day;
}int main()
{struct Date d1;Date d2;Date d3;d2.Init(2025, 8, 1);return 0;
}
#include<iostream>
using namespace std;//兼容C的struct用法
typedef struct ListNodeC
{int val;struct ListNodeC* next;
}LTNodeC;//CPP
struct ListNodeCPP
{int val;ListNodeCPP* next;
};int main()
{ListNodeCPP node;return 0;
}
  • 定義在類里?的成員函數默認為inline。

2、訪問限定符

在這里插入圖片描述

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

  • public修飾的成員在類外可以直接被訪問。protected和private修飾的成員在類外不能直接被訪問。

  • 訪問權限作?域從該訪問限定符出現的位置開始直到下?個訪問限定符出現時為?,如果后?沒有訪問限定符,作?域就到 }(類結束)。

  • class定義的成員未被訪問限定符修飾時默認為private,struct默認為public。

  • ?般成員變量都會被限制為private/protected,需要給別?使?的成員函數會放為public。

3、類域

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

  • 類域影響的是編譯的查找規則,下?程序中Init如果不指定類域Stack,那么編譯器就把Init當成全局函數,那么編譯時,找不到array等成員的聲明/定義在哪?,就會報錯。指定類域Stack,就是知道Init是成員函數,當前域找不到的array等成員,就會到類域中去查找。

#include<iostream>
using namespace std;class Stack
{
public:void Init(int n = 4);private:int* _a;int _top;int _capacity;
};void Stack::Init(int n)
{_a = (int*)malloc(sizeof(int) * n);if (_a == nullptr){perror("malloc fail");return;}_capacity = n;_top = 0;
}int main()
{Stack st;st.Init();return 0;
}

二、實例化

1、實例化概念

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

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

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

#include<iostream>
using namespace std;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和d2Date d1;Date d2;d1.Init(2025,5,1);d1.Print();d2.Init(2025, 7, 29);d2.Print();return 0;
}

2、對象??

類實例化出的每個對象,都有獨?的數據空間,所以對象中肯定包含成員變量,那么是否包含成員函數呢??先函數被編譯后是?段指令,對象中沒辦法存儲,這些指令存儲在?個單獨的區域(代碼段),因此只能存儲成員函數的指針。再分析?下,對象中是否有存儲指針的必要呢,Date實例化d1和d2兩個對象,d1和d2都有各?獨?的成員變量_year/_month/_day存儲各?的數據,但是d1和d2的成員函數Init/Print指針卻是?樣的,存儲在對象中就浪費了。如果?Date實例化100個對象,那么成員函數指針就重復存儲100次,太浪費了。

還要注意,其實函數指針是不需要存儲的,函數指針是?個地址,調?函數被編譯成匯編指令[call 地址],其實編譯器在編譯鏈接時,就要找到函數的地址,不是在運?時找,只有動態多態是在運?時找,就需要存儲函數地址。

上?我們分析了對象中只存儲成員變量,C++規定類實例化的對象也要符合內存對?的規則。
內存對?規則:
①:第?個成員位于結構體偏移量為0的地址處。

②:其他成員變量要對?到對?數整數倍的地址處。

注意:對?數=編譯器默認的?個對?數與該成員??的較?值,VS中默認的對?數為8。

③:嵌套的結構體對齊到自己成員中最大對齊數的整數倍。

④ :結構體總??為:最?對?數(含嵌套結構體的對齊數)的整數倍。

#include<iostream>
using namespace std;// 計算?下A/B/C實例化的對象是多大? 
class A
{
public:void Print(){cout << _ch << endl;}private:char _ch;int _i;
};class B
{
public:void Print(){//...}
};class C
{};int main()
{A a;B b;C c;cout << sizeof(a) << endl;cout << sizeof(b) << endl;cout << sizeof(c) << endl;return 0;
}

實例化對象a的大小計算:
在這里插入圖片描述

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

上?的程序運?后,我們看到沒有成員變量的B和C類對象的??是1,為什么沒有成員變量還要給1個字節呢?因為如果?個字節都不給,怎么表?對象存在過呢!所以這?給1字節,純粹是為了占位標識對象存在。

三、this指針

  • Date類中有 Init 與 Print 兩個成員函數,函數體中沒有關于不同對象的區分,那當d1調?Init和Print函數時,該函數是如何知道應該訪問的是d1對象還是d2對象呢?那么這?就要看到C++給了?個隱含的this指針解決這?的問題。

  • 編譯器編譯后,類的成員函數默認都會在形參第?個位置,增加?個當前類類型的指針,叫做this指針。?如Date類的Init的真實原型為: void Init(Date* const this, int year, int month, int day)

  • 類的成員函數中訪問成員變量,本質都是通過this指針訪問的,如Init函數中給_year賦值, this->_year = year

  • C++規定不能在實參和形參的位置顯?的寫this指針(編譯時編譯器會處理),但是可以在函數體內顯?使?this指針。

#include<iostream>
using namespace std;class Date
{
public://void Init(Date* const this, int year, int month, int day)void Init(int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}//void Print(Date* const this)void Print(){cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;Date d2;//d1.Init(&d1,2025,5,1)d1.Init(2025, 5, 1);//d1.Print(&d1)d1.Print();//d2.Init(&d2,2025,10,1)d2.Init(2025, 10, 1);//d2.Print(&d2)d2.Print();return 0;
}

在這里插入圖片描述

四、C++和C語?實現Stack對?

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

在這里插入圖片描述

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

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

C實現Stack:

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;void STInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = ps->capacity = 0;
}void STDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}void STPush(ST* ps, STDataType x)
{assert(ps);//檢查空間大小if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity = newcapacity;}//入棧ps->a[ps->top] = x;ps->top++;
}bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));ps->top--;
}STDataType STTop(ST* ps)
{assert(ps);assert(!STEmpty(ps));return ps->a[ps->top - 1];
}int STSize(ST* ps)
{assert(ps);return ps->top;
}int main()
{ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d\n", STTop(&s));STPop(&s);}STDestroy(&s);return 0;
}

C++實現Stack:

#include<iostream>
#include<assert.h>
#include<stdbool.h>
using namespace std;typedef int STDataType;
class Stack
{
public://成員函數void Init(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (_a == nullptr){perror("malloc fail");return;}_capacity = n;_top = 0;}void Push(STDataType x){//檢查空間大小if (_top == _capacity){int newcapacity = _capacity * 2;STDataType* tmp = (STDataType*)realloc(_a, sizeof(STDataType) * newcapacity);if (tmp == NULL){perror("realloc fail");return;}_a = tmp;_capacity = newcapacity;}//入棧_a[_top++] = x;}void Pop(){assert(_top > 0);--_top;}bool Empty(){return _top == 0;}int& Top(){assert(_top > 0);return _a[_top - 1];}void Destroy(){free(_a);_a = nullptr;_top = _capacity = 0;}private://成員變量STDataType* _a;int _capacity;int _top;
};int main()
{Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);while (!s.Empty()){printf("%d\n", s.Top());s.Pop();}s.Destroy();return 0;
}

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

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

相關文章

UnityURP 扭曲屏幕效果實現

UnityURP 扭曲屏幕效果實現前言項目下載URPGrabPass空間扭曲著色器實現添加可視化控制創建材質球并設置補充粒子使用步驟CustomData映射移動設備優化鳴謝前言 在Unity的Universal Render Pipeline (URP) 中&#xff0c;傳統的GrabPass功能被移除&#xff0c;借助URPGrabPass工…

(三)軟件架構設計

2024年博主考軟考高級系統架構師沒通過&#xff0c;于是決定集中精力認真學習系統架構的每一個環節&#xff0c;并在2025年軟考中取得了不錯的成績&#xff0c;雖然做信息安全的考架構師很難&#xff0c;但找對方法&#xff0c;問題就不大&#xff01; 本文主要是博主在學習過程…

切記使用mt19937構造隨機數

在做 Kazaee CodeForces - 1746F 這個問題的時候&#xff0c;最初的時候使用了ran()&#xff0c;然后一直WA&#xff0c;遂改成mt19937&#xff0c;順利通過本道題。 mt19937 Rand(time(0)); 調用隨機數時候&#xff0c;使用&#xff1a; Rand() & 1 注意看&#xff0…

基于N32G45x+RTT驅動框架的定時器外部計數

時鐘選擇 高級控制定時器的內部時鐘:CK_INT: 兩種外部時鐘模式: 外部輸入引腳 外部觸發輸入 ETR 內部觸發輸入(ITRx):一個定時器用作另一個定時器的預分頻器 外部時鐘原理 通過配置 TIMx_SMCTRL.SMSEL=111 選擇該模式。 計數器可以配置為在所選輸入的時鐘上升沿或下降沿 …

[特殊字符] Ubuntu 下 MySQL 離線部署教學(含手動步驟與一鍵腳本)

適用于 Ubuntu 20.04 / 22.04 無網絡環境部署 MySQL。 建議初學者先按手動方式部署一遍理解原理&#xff0c;再使用自動化腳本完成批量部署。&#x1f4c1; 一、準備工作 ? 1. 虛擬機環境 系統&#xff1a;Ubuntu 22.04&#xff08;或兼容版本&#xff09;環境&#xff1a;無網…

系統一個小時多次Full GC,導致系統線程停止運行,影響系統的性能,可靠性

背景&#xff1a; 某一天系統出現了請求超時&#xff0c;然后通過日志查看&#xff0c;程序執行到某一個位置&#xff0c;直接停下來來了&#xff0c;或者說所有的線程的執行都停下來了。而且是該時間段&#xff0c;請求處理變慢。排查相關的服務&#xff0c;并沒有出現死鎖&am…

使用OMV+NextCloud搭建私有云

原文地址&#xff1a;使用OMVNextCloud搭建私有云 – 無敵牛 歡迎參觀我的網站&#xff1a;無敵牛 – 技術/著作/典籍/分享等 OpenMediaVault&#xff08;簡稱OMV&#xff09;是一款基于Debian的開源網絡存儲&#xff08;NAS&#xff09;操作系統&#xff0c;提供Web管理界面&…

Codeforces Round 1008 (Div. 2)

A. Final Verdict 題目大意 給你一個數組a&#xff0c;每次把他拆分為等長的k個子序列&#xff0c;然后用子序列的平均數替換掉這個子序列&#xff0c;問最后能不能讓數組只剩下一個數字x 解題思路 無論怎么劃分&#xff0c;最后的總值是不變的&#xff0c;所以只需要看總和…

python轉移安裝目錄到D盤

遷移python安裝路徑第一步&#xff1a;移動目錄第二步&#xff1a;修改環境變量之前沒有設置之前設置過第一步&#xff1a;移動目錄 源路徑&#xff1a; C:\Users\Emma.ZRF\AppData\Local\Programs\Python\Python38 原環境變量 C:\Users\Emma.ZRF\AppData\Local\Programs\Pyth…

C#垃圾回收機制:原理與實踐

C#垃圾回收機制:原理與實踐 一、垃圾回收:C#內存管理的“幕后功臣”? 二、GC的核心引擎:基于代的優化策略 三、Demo展示 1. 簡單對象的垃圾回收示例 2. 基于代的回收示例 四、常用方法 五、推薦使用的場景 六、注意事項 管住手:避免濫用 GC.Collect() 析構函數:保持輕量 …

基于SpringBoot+MyBatis+MySQL+VUE實現的名城小區物業管理系統(附源碼+數據庫+畢業論文+開題報告+部署教程+配套軟件)

摘要 當下&#xff0c;正處于信息化的時代&#xff0c;許多行業順應時代的變化&#xff0c;結合使用計算機技術向數字化、信息化建設邁進。以前相關行業對于物業信息的管理和控制&#xff0c;采用人工登記的方式保存相關數據&#xff0c;這種以人力為主的管理模式已然落后。本人…

3DXML 轉換為 UG 的技術指南及迪威模型網在線轉換推薦

一、3DXML 轉換為 UG 的必要性 &#xff08;一&#xff09;軟件功能利用需求 3DXML 格式由達索系統開發&#xff0c;主要用于在其相關產品&#xff08;如 CATIA、SOLIDWORKS 和 3DEXPERIENCE 等&#xff09;中進行 3D 數據交換與輕量化可視化。它雖然能夠很好地在達索生態內實…

無人機光伏巡檢缺陷檢出率↑32%:陌訊多模態融合算法實戰解析

原創聲明本文為原創技術解析&#xff0c;引用來源標注 “陌訊技術白皮書”&#xff0c;禁止未經授權的轉載與改編。摘要在無人機光伏巡檢場景中&#xff0c;邊緣計算優化與復雜場景魯棒性是提升檢測效率的核心挑戰。本文解析陌訊多模態融合算法在光伏板熱斑、隱裂等缺陷檢測中的…

倉庫管理系統-15-前端之管理員管理和用戶管理

文章目錄 1 后臺查詢用戶列表 1.1 null和空字符串的檢查 1.2 UserController.java 2 管理員管理 2.1 傳遞參數roleId=1 2.2 admin/AdminManage.vue 3 用戶管理 3.1 傳遞參數roleId=2 3.2 user/UserManage.vue 管理員管理和用戶管理,與之前的Main.vue的內容基本一致,無非是管理…

個人筆記UDP

UDP消息發送發送端? import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; ? //不需要連接服務器 public class UdpClientDemo01 {public static void main(String[] args) throws Exception {/…

26屆算法秋招_baidu筆試_算法編程題。

給定2個字符串str1、str2&#xff0c;計算把str1轉變為str2的最小操作數。可執行的操作有&#xff1a;插入一個字符修改一個字符刪除一個字符解題&#xff1a;這是一個經典的編輯距離問題&#xff0c;通常使用動態規劃解決。定義dp[i][j]表示將str1的前i個字符轉換為str2的前j個…

uniapp-vue3來實現一個金額千分位展示效果

前言&#xff1a;uniapp-vue3來實現一個金額千分位展示效果實現效果&#xff1a;實現目標&#xff1a;1、封裝組件&#xff0c;組件內部要實現&#xff0c;input輸入金額后&#xff0c;聚焦離開后&#xff0c;金額以千分位效果展示&#xff0c;聚焦后展示大寫金額的彈框隨時寫的…

途游Android面試題及參考答案

對 Java 面向對象的理解是什么?多態的實現方法有哪些? Java 面向對象是一種編程思想,核心在于將現實世界中的事物抽象為 “對象”,每個對象由 “屬性”(數據)和 “方法”(行為)組成,通過對象之間的交互完成功能。其核心特性包括封裝、繼承和多態: 封裝是指將對象的屬…

通過filezilla在局域網下實現高速傳輸數據

一. filezilla安裝 1.1 linux安裝 sudo apt update sudo apt install openssh-server1.2 windows安裝 windows安裝可以參考這篇文章 二. 使用方法 2.1 wifi下使用方法 直接查看想要連接的電腦的ip&#xff0c;其他的按照有線網絡設置好了ip之后進行連接就行。 2.2 有線網…

python的易物小店交換系統

前端開發框架:vue.js 數據庫 mysql 版本不限 后端語言框架支持&#xff1a; 1 java(SSM/springboot)-idea/eclipse 2.NodejsVue.js -vscode 3.python(flask/django)–pycharm/vscode 4.php(thinkphp/laravel)-hbuilderx 數據庫工具&#xff1a;Navicat/SQLyog等都可以 在需求分…