[C++類和對象]類和對象的引入

面向過程和面向對象

C語言是面向過程的,關注的是過程,分析出求解問題的步驟,通過函數調用來逐步解決問題

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

類的引入

C語言結構體中只能定義變量,在C++中,結構體不僅僅可以定義變量,而且可以定義函數,

例如 :之前用C語言實現的棧,結構體中只能定義變量,現在已C++的方式實現,不僅可以定義變量,而且還可以在結構體定義函數

?對于結構體的定義,在C++中 更喜歡用class來定義

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

?class為定義類的關鍵字,className為類的名字,{}中為類的主體,注意類定義結束之后后面的分號不能省略

類體中內容稱為類的成員:類的變量稱為類的屬性或成員變量;類中的函數被稱為類的方法或者是類的成員函數

類的兩種第一方式

1.聲明和定義全部放在類體中,需要主義:成員函數如果在類中定義,編譯器可能會把函數當作內聯函數來做處理

2.類聲明放在.h文件中,成員函數定義在.cpp的文件中,

如果這樣的話,要在函數前加上類名

C++里類域中的成員變量通常書寫前加一個_區分,可以寫在前面例如:_year,或者year_

例如:我們的成員變量如果使用的year不進行區分

傳入的變量year = year month = month day = day,通常會報錯

因為編譯器無法區分變量是函數形參還是成員變量

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year; // year_  m_yearint _month;int _day;
};int main()
{Date d;d.Init(2024, 3, 31);return 0;
}

?類的訪問限定符及封裝

訪問限定符

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

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.

封裝

面向對象的三大特性?

封裝 繼承 多態

在類和對象階段,主要是研究類的封裝性,什么事封裝?

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

封裝的本質是一種管理,讓用戶更方便使用類

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

類的作用域

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

class Person
{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int _age;
};
// 這里需要指定PrintPersonInfo是屬于Person這個類域
void Person::PrintPersonInfo()
{cout << _name << " "<< _gender << " " << _age << endl;
}

類的實例化

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

1.類是對對象進行描述的,是一個模型一樣的東西,限定了類有哪些成員,定義出一個類并沒有分配實際的內存空間來存儲他.

2.一個類可以實例化出多個對象,實例化出的對象,占用實際的物理空間,存儲類成員變量

class Person
{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int _age;
};
int main()
{Person._age = 100;
// 編譯失敗:error C2059: 語法錯誤:“.”
//并且成員變量都是私有的不能直接使用return 0;
}

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

打個比方,類實例化出對象就像現實中使用建筑設計圖建造出房子,類就像是設計圖,只設計出需要什么東西,但沒有實體存在,同樣類也是一個設計,實例化出的對象才能實際存儲數據,占用物理空間

類對象模型

如何計算類對象的大小

class A
{
public:void PrintA(){cout<<_a<<endl;}
private:char _a;
};

類中既可以有成員變量,又可以有成員函數,那么一個類的對象中包含了什么?如何計算一個類的大小

類對象的存儲方式猜測

對象中包含類的各個成員

缺陷:每個對象中成員變量是不同的,但是調用同一份函數,如果按照此種方式存儲,當一個類創建多個對象時,每個對象中都會保存一份代碼,相同代碼保存多次,浪費空間。那么如何解決呢?
只保存成員變量,成員函數存放在公共的代碼段
// 類中既有成員變量,又有成員函數
class A1 {
public:void f1(){}
private:int _a;
};
// 類中僅有成員函數
class A2 {
public:void f2() {}
};
// 類中什么都沒有---空類
class A3
{};
sizeof(A1) : __4__ __ sizeof(A2) : _1___ __ sizeof(A3) : ___1_ __
結論:一個類的大小,實際就是該類中 成員變量 ”之和,當然要注意 內存對齊
注意空類的大小,空類比較特殊,編譯器給了空類一個字節來唯一標識這個類的對象。

this指針

我們先來定義一個日期類

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}//void Print(Date* this)void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year; // 年int _month; // 月int _day; // 日int a;
};
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++ 編譯器給每個 非靜態的成員函數 增加了一個隱藏的指針參 數,讓該指針指向當前對象 ( 函數運行時調用該函數的對象 ) ,在函數體中所有 成員變量 的操作,都是通過該 指針去訪問。只不過所有的操作對用戶是透明的,即用戶不需要來傳遞,編譯器自動完成
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}//void Print(Date* const this)void Print(){//cout <<this-> _year << "-" << this->_month << "-" <<this-> _day << endl;cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year; // 年int _month; // 月int _day; // 日int a;
};
int main()
{Date d1, d2;d1.Init(2022, 1, 11);d2.Init(2022, 1, 12);//d1.Print(&d1);d1.Print();//d2.Print(&d2);d2.Print();return 0;
}

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

this指針存在哪里?

this指針可以為空嗎?

// 1. 下面程序編譯運行結果是? A 、編譯報錯 B 、運行崩潰 C 、正常運行

傳遞空指針不會報編譯錯誤,沒有訪問,所以正常運行

class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();return 0;
}

?// 1.下面程序編譯運行結果是? A、編譯報錯 B、運行崩潰 C、正常運行

運行崩潰

class A
{
public:void PrintA(){cout << _a << endl;//cout << this->_a << endl;}
private:int _a;
};
int main()
{A* p = nullptr;//p->PrintA(&p);p->PrintA();return 0;
}

1. this 指針存在哪里?

this?通常不占用對象內存,而是作為隱藏參數傳遞,可能存棧上。

有些存在ecx寄存器上

2. this 指針可以為空嗎?
this指針理論上可以為空,運行起來沒有錯誤
如果函數不訪問成員變量,可以為空,正常運行
如果對this指針進行訪問的時候,會導致崩潰

?把C語言中的結構體用C++重新實現一下

#include <iostream>
#include <stdlib.h>
#include <stdbool.h>
using namespace std;typedef int DataType;
class Stack
{
public:void Init(int n = 4){_arry = (DataType*)malloc(sizeof(DataType)*n);if (_arry == NULL){perror("malloc is fail");return;}_size = 0;_capacity = n;}int size(){return _size;}bool empty(){return _size == 0;}void push(DataType data){Checkcapacity();_arry[_size] = data;_size++;}void Pop(){if (empty()){return;}_size--;}int top(){return _arry[_size - 1];}void Destory(){free(_arry);_arry = nullptr;_capacity = 0;_size = 0;}
private:void Checkcapacity(){if (_size == _capacity){int newcapacity = _capacity * 2;DataType* temp = (DataType*)realloc(_arry, newcapacity * sizeof(DataType));if (temp == NULL){perror("realloc fail");return;}_arry = temp;_capacity = newcapacity;}}
private:DataType* _arry;int _size;int _capacity;
};int main()
{Stack st;st.Init();st.push(1);st.push(2);st.push(3);st.push(4);st.push(5);while (!st.empty()){	cout << st.top() << " ";st.Pop();}return 0;
}

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

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

相關文章

AWS之存儲服務

目錄 一、傳統存儲術語 二、傳統存儲與云存儲的關系 三、云存儲之AWS 使用場景 文件存儲 數據塊存儲 對象存儲 EBS、EFS、S3對比 EBS塊存儲 S3對象存儲 S3 使用案例 S3 存儲類 EFS文件存儲 一、傳統存儲術語 分類 接口/技術類型 應用場景特點 關系及區別 機械硬…

WPDRRC 模型:構建動態閉環的信息安全防御體系

WPDRRC 模型是一種信息安全整體架構設計模型&#xff0c;由預警&#xff08;Warning&#xff09;、保護&#xff08;Protection&#xff09;、檢測&#xff08;Detection&#xff09;、反應&#xff08;Reaction&#xff09;、恢復&#xff08;Recovery&#xff09;和反擊&…

Redis 數據類型詳解(二):Hash 類型全解析

文章目錄 一、什么是 Redis 的 Hash 類型&#xff1f;二、Hash為什么在有些時候比String好用三、常見命令1.HSET key field value2.HGET key field3.HMSET4.HMGET5.HGETALL6.HKEYS7.HVALS8.HINCRBY9.HSETNX 四、應用場景五、性能優勢六、注意事項總結 提示&#xff1a;以下是本…

Go Modules 的基本使用

在 Go Modules 項目中&#xff0c;首次運行時下載依賴包的正確流程需要根據項目情況區分處理。以下是詳細步驟和最佳實踐&#xff1a; 一、首次初始化項目的標準流程 1.1 創建項目目錄并初始化模塊 mkdir myproject && cd myproject go mod init github…

RISC-V AIA SPEC學習(五)

第六章 Interrupts for Virtual Machines(VS Level) 核心內容 1.VS級別外部中斷支持:?? ??客戶中斷文件(Guest Interrupt File)??:虛擬機的每個vCPU擁有獨立的IMSIC中斷文件,允許直接接收設備MSI。??vstopi CSR??:類似stopei,用于虛擬機內部處理最高優先級中…

【Python-Day 11】列表入門:Python 中最靈活的數據容器 (創建、索引、切片)

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

【AXI總線專題】-AXI-LITE總線解讀

【AXI總線專題】-AXI-LITE總線解讀 1.axi-lite概述2.信號定義Write address channelWrite data channelWrite response channelRead address channelRead data channel 3.測試4.仿真波形5.工程文件 參考手冊 《3-2-03米聯客2022版AXI4總線專題-20211123.pdf》 《IHI0022E_amba_…

在企業級項目中高效使用 Maven-mvnd

1、引言 1.1 什么是 Maven-mvnd? Maven-mvnd 是 Apache Maven 的一個實驗性擴展工具(也稱為 mvnd),基于守護進程(daemon)模型構建,目標是顯著提升 Maven 構建的速度和效率。它由 Red Hat 推出,通過復用 JVM 進程來減少每次構建時的啟動開銷。 1.2 為什么企業在構建過…

網絡字節序 - 大端

回顧主機字節序 - 大小端 發送主機將發送緩沖區中的數據按內存地址從低到高的順序發出接收主機把從網絡上接收到的數據按內存地址從底到高的順序依次保存到接收緩沖區TCP/IP 規定&#xff0c;網絡數據流應采用大端字節序&#xff0c;即低地址高字節&#xff0c;也就是說&#…

《被討厭的勇氣》書摘

阿德勒心理學考慮的不是過去的“原因”&#xff0c;而是現在的“目的”。你的朋友并不是因為不想到外面去&#xff0c;才制造出不安的情緒。是先有了“不出去”這個目的&#xff0c;之后才會為了達到這個目的而制造出不安或者恐懼之類的情緒。 個人見解&#xff1a;這是阿德勒…

打造專屬AI好友:小智AI聊天機器人詳解

打造專屬AI好友&#xff1a;小智AI聊天機器人詳解 在當下的科技熱潮中&#xff0c;AI正迅速改變著我們的生活&#xff0c;成為了科技領域的新寵。而今&#xff0c;借助開源項目的力量&#xff0c;你可以親手打造一個智能小助手——小智AI聊天機器人。它不僅是一個技術探索的窗…

如何利用爬蟲獲得1688商品詳情:實戰指南

在電商運營和市場分析中&#xff0c;獲取1688商品詳情數據是一項重要任務。本文將詳細介紹如何利用爬蟲技術獲取1688商品詳情&#xff0c;包括準備工作、爬蟲實現步驟以及注意事項。 一、準備工作 &#xff08;一&#xff09;注冊1688開放平臺賬號 在1688開放平臺注冊開發者…

如何優化系統啟動時間--基于米爾瑞薩MYD-YG2LX開發板

1.概述 MYD-YG2LX采用瑞薩RZ/G2L作為核心處理器&#xff0c;該處理器搭載雙核Cortex-A551.2GHzCortex-M33200MHz處理器&#xff0c;其內部集成高性能3D加速引擎Mail-G31 GPU(500MHz)和視頻處理單元&#xff08;支持H.264硬件編解碼&#xff09;,16位的DDR4-1600 / DDR3L-1333內…

QML 圖像變換(縮放、平移、旋轉)

目錄 引言相關閱讀基礎知識工程結構核心代碼解析示例1&#xff1a;圖像縮放&#xff08;ImageScale.qml&#xff09;代碼說明運行效果 示例2&#xff1a;圖像平移&#xff08;ImageTransform.qml&#xff09;代碼說明運行效果 示例3&#xff1a;圖像旋轉&#xff08;ImageRotat…

Linux 系統命令使用指南1

適用于 Red Hat / CentOS / Rocky Linux 等系統的基本初始化配置操作。 &#x1f512; 1. 關閉 SELinux&#xff08;臨時生效&#xff09; setenforce 0?? 注意&#xff1a;此命令僅臨時關閉 SELinux&#xff0c;重啟后可能恢復。要永久關閉&#xff0c;請修改 /etc/selinux…

1.2.1 Linux音頻系統發展歷程簡介

Linux音頻系統的發展經歷了從最初的簡單驅動到今天多層次、模塊化音頻架構。簡要梳理其主要歷程&#xff1a; 早期的OSS&#xff08;Open Sound System&#xff09; 在90年代及2000年代初&#xff0c;Linux主要使用OSS來支持音頻。OSS直接為硬件設備&#xff08;如聲卡&#…

【Linux操作系統】第一彈——Linux基礎篇

文章目錄 &#x1f4a1; 一. Linux的基本常識&#x1fa94; 1.1 linux網絡連接三種方式&#x1fa94;1.2 虛擬機的克隆&#x1fa94;1.3 虛擬機的快照&#x1fa94;1.4 虛擬機的遷移和刪除&#x1fa94;1.5 vmtools工具 &#x1f4a1;二. Linux的目錄結構&#x1fa94;2.1 Linu…

STM32printf重定向到串口含armcc和gcc兩種方案

STM32串口重定向&#xff1a;MDK與GCC環境下需重寫的函數差異 在嵌入式開發中&#xff0c;尤其是使用 STM32系列微控制器 的項目中&#xff0c;調試信息的輸出是不可或缺的一部分。為了方便調試&#xff0c;開發者通常會選擇將 printf 等標準輸出函數通過 UART 串口發送到 PC …

C++ 文本讀寫與二進制讀寫的底層機制

1.文件的打開方式 1.文本打開 在windows中,寫入時會將\n換成\r\n,讀出時\r\n會讀出\n linux對\n讀寫不做處理 2.二進制打開 對\n讀寫不做處理 2.文本讀寫 1.數據要先變成字符串再寫進緩沖區 2.字符串直接寫進緩沖區就是 3.c對文本讀寫的支持 istream/ostream中重載了對…

02 mysql 管理(Windows版)

一、啟動及關閉 MySQL 服務器 1.1 通過 “服務” 管理工具 winr打開運行&#xff0c;輸入services.msc 找到MySQL80&#xff0c;這個是我們在安裝mysql的時候給的服務的名稱&#xff0c;具體見文章mysql 安裝 右鍵選擇啟動或者停止。 1.2 通過命令提示符 1.2.1 關閉命令…