【C++初階】---類和對象(上)

1.類的定義

1.1類的定義格式

? class為定義類的關鍵字,Data為類的名字,{}中為類的主體,注意類定義結束時后?分號不能省略。類體中內容稱為類的成員:類中的變量稱為類的屬性或成員變量;類中的函數稱為類的?法或者成員函數
? 為了區分成員變量,?般習慣上成員變量會加?個特殊標識,如成員變量前?或者后?加_或者m開頭,注意C++中這個并不是強制的,只是?些慣例,具體看公司的要求。

#include<iostream>
using namespace std;//類的定義
class Data
{
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()
{Data d;d.Init(2025, 3, 23);d.Print();return 0;
}

在這里插入圖片描述
? C++中struct也可以定義類,C++兼容C中struct的?法,同時struct升級成了類,明顯的變化是struct中可以定義函數,?般情況下我們還是推薦?class定義類。
(需要注意的是struct和class兩種類有區別,下面我會提到)

struct Data
{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;
};

? 定義在類?的成員函數默認為inline。

1.2限定訪問符

? C++?種實現封裝的?式,?類將對象的屬性與?法結合在?塊,讓對象更加完善,通過訪問權限選擇性的將其接?提供給外部的??使?。
? public修飾的成員在類外可以直接被訪問;protected和private修飾的成員在類外不能直接被訪問,protected和private是?樣的,以后繼承章節才能體現出他們的區別。
? 訪問權限作?域從該訪問限定符出現的位置開始直到下?個訪問限定符出現時為?,如果后?沒有訪問限定符,作?域就到}即類結束
? class定義成員沒有被訪問限定符修飾時默認為private,struct默認為public
(這就是兩種類的區別)
? ?般成員變量都會被限制為private/protected,需要給別?使?的成員函數會放為public。
在這里插入圖片描述

1.3類域

? 類定義了?個新的作?域,類的所有成員都在類的作?域中,在類體外定義成員時,需要使?::作?域操作符指明成員屬于哪個類域。
? 類域影響的是編譯的查找規則,下?程序中Init如果不指定類域Stack,那么編譯器就把Init當成全局函數,那么編譯時,找不到array等成員的聲明/定義在哪?,就會報錯。指定類域Stack,就是知道Init是成員函數,當前域找不到的array等成員,就會到類域中去查找。

//類域
#include<iostream>
using namespace std;class Stack
{
public:void Init(int n = 4);void Print(){cout << capacity << endl;}
private:int* array;int capacity;int top;
};void Stack::Init(int n)
{array = (int*)malloc(sizeof(int) * n);if (array == nullptr)//C++中的空指針{perror("malloc fail!\n");return;}capacity = n;top = 0;
}int main()
{Stack st;st.Init();st.Print();return 0;
}

在這里插入圖片描述

2.實例化

2.1實例化的概念

? ?類類型在物理內存中創建對象的過程,稱為類實例化出對象。
? 類是對象進??種抽象描述,是?個模型?樣的東西,限定了類有哪些成員變量,這些成員變量只是聲明,沒有分配空間,?類實例化出對象時,才會分配空間。
? ?個類可以實例化出多個對象,實例化出的對象占?實際的物理空間,存儲類成員變量。
打個??:類實例化出對象就像現實中使?建筑設計圖建造出房?,類就像是設計圖,設計圖規劃了有多少個房間,房間??功能等,但是并沒有實體的建筑存在,也不能住?,?設計圖修建出房?,房?才能住?。同樣類就像設計圖?樣,不能存儲數據,實例化出的對象分配物理內存存儲數據。
在這里插入圖片描述

//實例化
#include<iostream>
using namespace std;class Data
{
public:void Init(int year = 2020, int month = 3, int day = 23){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private://這里只是聲明,沒有開辟空間int _year;int _month;int _day;
};int main()
{//實例化出d1和d2Data d1;Data d2;d1.Init(2020, 2, 2);d1.Print();d2.Init(2023, 2, 3);d2.Print();return 0;
}

2.2對象的大小

分析一下類對象中哪些成員呢?類實例化出的每個對象,都有獨?的數據空間,所以對象中肯定包含成員變量,那么成員函數是否包含呢??先函數被編譯后是?段指令,對象中沒辦法存儲,這些指令存儲在?個單獨的區域(代碼段),那么對象中?要存儲的話,只能是成員函數的指針。再分析?下,對象中是否有存儲指針的必要呢,Date實例化d1和d2兩個對象,d1和d2都有各?獨?的成員變量_year/_month/_day存儲各?的數據,但是d1和d2的成員函數Init/Print指針卻是?樣的,存儲在對象中就浪費了。如果?Date實例化100個對象,那么成員函數指針就重復存儲100次,太浪費了。
所以對象中只存儲成員變量,而成員函數存儲在公共代碼區中
在這里插入圖片描述
而C++規定實例化的對象也要符合內存對齊規則:
內存對?規則
? 第?個成員在與結構體偏移量為0的地址處。
? 其他成員變量要對?到某個數字(對?數)的整數倍的地址處。
? 注意:對?數=編譯器默認的?個對?數與該成員??的較?值。
? VS中默認的對?數為8
? 結構體總??為:最?對?數(所有變量類型最?者與默認對?參數取最?)的整數倍。
? 如果嵌套了結構體的情況,嵌套的結構體對?到??的最?對?數的整數倍處,結構體的整體??就是所有最?對?數(含嵌套結構體的對?數)的整數倍。
就拿以下代碼舉例:

//計算類A的大小
class A
{
public:void Print();void Init(int n = 4);private:char c;int n;int a;
};

存儲如下:
在這里插入圖片描述

在這里插入圖片描述
當類中沒有成員變量的時候,對象的大小是多少呢?就拿以下代碼來說,類B和類C中都沒有成員變量,他們兩個類所創造出來的對象的大小是1個字節,之所以給1個字節是為了占位標識對象的存在。

#include<iostream>
using namespace std;class A
{
public:void Print(){cout << _year << endl;}
private:int _year;char _name;int _std;
};class B
{
public:void Print(){cout << "B" << endl;}
};class C
{};int main()
{A a;B b;C c;cout << sizeof(a) << endl;cout << sizeof(b) << endl;cout << sizeof(c) << endl;return 0;
}

在這里插入圖片描述

3.this指針

3.1this指針的概念

? 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指針。
? this指針一般存儲在內存中的棧區,但一個對象調用成員函數,編譯器會把對象的地址(也就是this指針的值)壓入棧中。成員函數在執行時,會從棧中獲取this指針的值,從而能訪問該對象的成員。

//this指針
#include<iostream>
using namespace std;class Data
{
public://可以在函數體內寫this,實參和形參部分不能寫void Init(int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}void Print(){cout << this->_year << "/" << this->_month << "/" << this->_day << endl;}private:int _year;int _month;int _day;
};int main()
{Data d1;Data d2;d1.Init(2023, 3, 23);d1.Print();d2.Init(2025, 1, 4);d2.Print();return 0;
}

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

3.1.1題目練習

我們來判斷一下以下兩段代碼的運行結果是什么?

//代碼1
#include<iostream>
using namespace std;class A
{
public:void Print(){cout << "A::Print()" << endl;}private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}//代碼2
#include<iostream>
using namespace std;class A
{
public:void Print(){cout << "A::Print()" << endl;cout << _a << endl;//不同處}private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}

以上兩端代碼的運行結果是:代碼1正常運行,代碼2運行奔潰。
為什么呢?因為我們看到,雖然兩端代碼的p指針雖然都是空指針,但代碼1并沒有訪問類中的成員變量,所以不存在對空指針進行引用的問題,但代碼2想要打印成員變量,這就涉及了對類中的成員變量的訪問,也就是代碼2的問題是對空指針進行引用操作,導致程序的錯誤訪問。
在這里插入圖片描述

4.C語言和C++實現棧Stack對比

? C++中數據和函數都放到了類??,通過訪問限定符進?了限制,不能再隨意通過對象直接修改數據,這是C++封裝的?種體現,這個是最重要的變化。這?的封裝的本質是?種更嚴格規范的管理,避免出現亂訪問修改的問題。
? C++中有?些相對?便的語法,?如Init給的缺省參數會?便很多,成員函數每次不需要傳對象地址,因為this指針隱含的傳遞了,?便了很多,使?類型不再需typedef?類名就很?便
1.封裝性:
C語言:使用結構體和函數來實現棧,數據(變量)和操作(函數)是分開的,需要手動傳遞結構體指針來操作數據,封裝性較差。
C++:使用類將數據(成員變量)和操作(成員函數)封裝在一起,通過對象來調整成員函數,封裝性更好,隱藏了內部實現細節。
2.安全性:
C語言:由于數據和操作分離,用戶可能會直接訪問和修改結構體中的數據,從而破壞棧的完整性。
C++:可以將成員變量私有(private),只能通過類得到成員函數來訪問和修改成員變量,提高了數據的安全性。

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 = 0;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>using namespace std;
typedef int STDataType;
class Stack
{
public:// 成員函數 void Init(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申請空間失敗");return;}_capacity = n;_top = 0;}void Push(STDataType x){if (_top == _capacity){int newcapacity = _capacity * 2;STDataType* tmp = (STDataType*)realloc(_a, newcapacity *sizeof(STDataType));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;size_t _capacity;size_t _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/pingmian/73600.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73600.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/73600.shtml

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

相關文章

Rust安裝并配置配置vscode編譯器

一. 下載rustup-init.exe rust下載網址&#xff1a;Getting started - Rust Programming Language 根據系統&#xff0c;選擇適合的exe文件 我選擇的的是右邊64bit的 打開下載的文件 輸入1&#xff0c;回車 二. Visual C 安裝 自動下載安裝vs 等待安裝完畢 三. Rust 安裝…

openGl片段著色器的含義

片段著色器的含義及代碼中的應用說明&#xff1a; 1. 片段著色器的基本概念 片段著色器&#xff08;Fragment Shader&#xff09;是OpenGL著色器管線中的關鍵組件&#xff0c;主要用于計算屏幕空間中每個片段&#xff08;對應像素&#xff09;的最終顏色。它是圖形渲染流程的…

事務的四大特性(ACID)詳解

事務的四大特性&#xff08;ACID&#xff09;詳解 在數據庫管理系統&#xff08;如 MySQL&#xff09;中&#xff0c;事務&#xff08;Transaction&#xff09; 是指一組要么全部執行、要么全部不執行的數據庫操作&#xff0c;通常用于確保數據的完整性和一致性。事務有四大核…

ubuntu設置開機自動運行應用

系統版本&#xff1a;Ubuntu 24.04.1 LTS桌面版 按招網上的資料顯示&#xff0c;當前版本主要的實現方式有以下兩種&#xff0c; 方式1&#xff1a;通過圖形界面的【啟動應用程序】設置開機自啟動&#xff1b;方式2&#xff1a;配置為服務實現開機自啟動。 但是在我的電腦上方…

ECharts各類炫酷圖表/3D柱形圖

一、前言 最近雞米花實現了各類的炫酷的圖表&#xff0c;有3D柱形圖、雙邊柱形圖以及異形柱形圖&#xff0c;好了&#xff0c;直接上圖&#xff1a; 二、效果圖 一個個來吧&#xff0c;下面就是代碼啦&#xff0c;注意&#xff0c;一下圖表展示的寬高均為800px*300px 三、異形橫…

機器人原點丟失后找回原點的解決方案與步驟

機器人原點丟失后找回原點的解決方案與步驟 在機器人運行過程中&#xff0c;原點丟失可能導致定位錯誤、運動失控等問題&#xff0c;常見于機械臂、AGV&#xff08;自動導引車&#xff09;、3D打印機等設備。以下是針對原點丟失問題的系統性解決方案及詳細步驟&#xff0c;涵蓋…

HCIP——園區網、VLAN

園區網 園區網搭建核心思路&#xff1a;冗余&#xff08;備份&#xff09;--- 保證其健壯性 1、設備冗余 2、線路冗余 3、網關冗余 4、ups&#xff08;不間斷電源&#xff09;冗余—— 能不斷電&#xff08;物理層&#xff09; 三層交換機和路由器的選擇&#xff1a; 三層交換…

虛擬機(二):Android 篇

虛擬機&#xff08;一&#xff09;&#xff1a;Java 篇 虛擬機&#xff08;二&#xff09;&#xff1a;Android 篇 Dalvik和JVM區別 Dalvik 基于寄存器&#xff0c;而 JVM 基于棧。 基于棧的架構具有更好的可移植性&#xff0c;因為其實現不依賴于物理寄存器基于棧的架構通常指…

Android Token的原理和本地安全存儲

Android Token的原理和本地安全存儲 前言 在移動應用開發中,Token是實現用戶身份驗證和授權的重要機制。本文將深入介紹Token的原理,以及在Android平臺上如何安全地存儲Token,幫助開發者構建可靠的身份驗證系統。 基礎知識 1. Token概述 1.1 Token的作用 身份驗證授權訪…

Vue Kubernetes項目 局部布局 下拉菜單

下拉菜單 [el-dropdown] 下拉菜單也比較簡單&#xff0c;就是類似于按鈕下面來一個下拉菜單。 示例Demo如下&#xff1a; <template><el-dropdown><span class"el-dropdown-link">下拉菜單<i class"el-icon-arrow-down el-icon--right&q…

Android之卡片式滑動

文章目錄 前言一、效果圖二、實現步驟1.主界面xml2.自定義的viewpage3.卡片接口類4.陰影和縮放變化類5.卡片adapter6.卡片adapter的xml7.style8.CardItem9.activity實現10.指示器drawable 總結 前言 對于這個需求&#xff0c;之前的項目也有做過&#xff0c;但是過于趕項目就沒…

(UI自動化測試web端)第二篇:元素定位的方法_css定位之css選擇器

看代碼里的【find_element_by_css_selector( )】( )里的表達式怎么寫&#xff1f; 文章介紹了第三種寫法css選擇器&#xff0c;你要根據網頁中的實際情況來判斷自己到底要用哪一種方法來進行元素定位。每種方法都要多練習&#xff0c;全都熟了之后你在工作當中使用起來元素定位…

使用vscode搭建pywebview集成vue項目示例

文章目錄 前言環境準備項目源碼下載一、項目說明1 目錄結構2 前端項目3 后端項目獲取python安裝包(選擇對應版本及系統) 三、調試與生成可執行文件1 本地調試2 打包應用 四、核心代碼說明1、package.json2、vite.config.ts設置3、main.py后端入口文件說明 參考文檔 前言 本節我…

C stm32f10x LED亮

#include<stm32f10x.h>int main(){#if 0 //APIOA 時鐘初始化unsigned int * p(unsigned int*)0x40021018;*p | 0x1<<2;//A0 推挽輸出p(unsigned int*)0x40010800;*p *p & ~0xf | 0x1;//A0低電平p(unsigned int*)0x4001080c;*p & ~0x1;#endifRCC->APB2E…

redux ,react-redux,redux-toolkit 簡單總結

Redux、React-Redux 和 Redux Toolkit 是協同工作的三個庫&#xff0c;各自承擔不同角色&#xff0c;相互協同。 Redux&#xff1a;基礎底座 底層狀態管理庫&#xff0c;負責狀態存儲、Action 派發和 Reducer 執行 ?React-Redux&#xff1a;連接 React 組件與 Redux Store 通…

智能制造:物聯網和自動化之間的關系

工業自動化 工業自動化是機器設備或生產過程在不需要人工直接干預的情況下按預期的目標實現測量、操縱等信息處理和過程控制的統稱。 在傳統的工業生產過程中&#xff0c;很多環節需要人工操作&#xff0c;比如設備調試、生產監控、質量檢測等。然而&#xff0c;隨著工業自動化…

“自動駕駛背后的數學” 專欄導讀

專欄鏈接&#xff1a; 自動駕駛背后的數學 專欄以“自動駕駛背后的數學”為主題&#xff0c;從基礎到深入&#xff0c;再到實際應用和未來展望&#xff0c;全面解析自動駕駛技術中的數學原理。開篇用基礎數學工具搭建自動駕駛的整體框架&#xff0c;吸引兒童培養興趣&#xff0…

集成學習(下):Stacking集成方法

一、Stacking的元學習革命 1.1 概念 Stacking&#xff08;堆疊法&#xff09; 是一種集成學習技術&#xff0c;通過組合多個基學習器&#xff08;base learner&#xff09;的預測結果&#xff0c;并利用一個元模型&#xff08;meta-model&#xff09;進行二次訓練&#xff0c…

Dubbo 全面解析:從 RPC 核心到服務治理實踐

一、分布式系統與 RPC 框架概述 在當今互聯網時代&#xff0c;隨著業務規模的不斷擴大&#xff0c;單體架構已經無法滿足高并發、高可用的需求&#xff0c;分布式系統架構成為主流選擇。而在分布式系統中&#xff0c;遠程服務調用&#xff08;Remote Procedure Call&#xff0…

vmware虛擬機突然連不上網

1.一般是自己的主機把服務給關掉了&#xff0c;右擊我的電腦&#xff0c;然后找到管理->服務&#xff0c;確保下面虛擬機的網絡服務是否打開 Vmware虛擬機突然連接不上網絡【方案集合】_vmware虛擬機連不上網-CSDN博客 2.識別到無效網絡 控制面板->網絡和共享中心&…