CPP_類和對象

面向對象:

更接近真實世界(關注各對象之間的關系,而非各步驟的進行)


  • 將結構體升級成立類

  • 類里面可以有:成員函數,成員變量

  • class Stack {
    public:void Init(int defaultCapacity=4 ) {_a = (int*)malloc(sizeof(int) * defaultCapacity);_capacity = defaultCapacity;_top = 0;}void Push(int x) {_a[_top++] = x;}void Destory() {free(_a);_a = nullptr;}
    private:int* _a;int _top;int _capacity;
    };
    int main() {Stack st;st.Init();st.Push(1);st.Destory();return 0;
    }
    
  • 訪問限定符(即訪問權限):

    • public:類外可以訪問
    • protected
    • private
    • 每一種訪問限定符的作用域是從當前限定符到下一個限定符
  • 一個類里面的函數,也可以聲明與定義分離(如果函數太長了話)(如果聲明和定義都直接寫在類里面,如果這些函數符合內聯規則,則默認都是內聯函數

  • //stack.c
    class Stack {
    public:void Init(int defaultCapacity=4);void Push(int x) {a[top++] = x;}
    }
    
  • //stack.h
    //指定類域
    void Stack::Init(int defaultCapacity=4 ) {a = (int*)malloc(sizeof(int) * defaultCapacity);capacity = defaultCapacity;top = 0;
    }
    

封裝
  • 本質上是一種更好的管理(便于用戶使用類)

  • 對于成員變量,只有在實例化某一個類的時候,才會為類里面的成員變量開辟空間(即它的定義)(也就相當于類其實是一種設計,并沒有實際的東西,只有實例化之后,才有這種設計對應的實例)

  • class Stack {
    private:int* _a;int _top;int _capacity;/*這些變量是聲明,不是定義(對于變量來說,是否開空間是區分聲明和定義的最大區別)所以在實例化對象的時候,才定義這些變量*/
    };
    
  • 對于某一個類的實例化對象來說,sizeof() 計算的是成員變量在經過內存對齊之后的總大小,不加成員函數。(因為對于每一個實例來說,都有一套成員變量都是單獨屬于它們自己的。但對于成員函數來說,所有實例的該方法都是一樣的,沒有必要每個實例都存儲一份成員函數,只需要在一個公用區域存一份,所有實例都訪問這一個就行了,所以sizeof()只有成員變量,沒有成員函數)

  • 如果一個類只有成員函數,或者什么都沒有,sizeof() 的計算結果是1。相當于這個類的對象默認占一個字節,相當于占一個位置,表示這個對象是存在的,但不存有效數據


This指針
  • 其實對于實例化對象來說,雖然成員函數是共用的,但每個實例調用時都是使用自己的成員變量的值,其實本質上是因為編譯器默認使用了this指針,將當前實例的地址傳給了成員函數,所以不同實例在調用的時候,使用的是自己的成員變量

  • class Date { 
    public:void print() {cout << year << " " << mon << " " << day;}void init() {year = 1;mon = 2;day = 3;}
    private:int year;int mon;int day;
    };
    int main() {Date d;d.init();d.print();return 0;
    }
    /*本質上其實是將當前實例的地址傳給了成員函數,所以不同實例在調用的時候,使用的是自己的成員變量void print(Date* this) {cout << this->year << " " << this->mon;}Date d;d.print(&d);
    */
    
  • this不能在形參和實參傳遞,但可以直接在函數內部使用

  • this指針是形參,所以和普通參數一樣,是存在棧里面的,作為棧幀的一部分(隨壓棧一起)


類的六大默認成員函數(不顯式寫出編譯器就會自行生成)
  • 一.構造函數(完成實例的初始化):

    • 函數名與類名相同

    • 無返回值(也不需要寫void)

    • 在對象實例化的時候編譯器自動調用對應的構造函數(如果不寫構造函數,則編譯器會自動生成默認的構造函數)

    • 構造函數可以重載(多種初始化的方式)

    • 沒有自己寫的構造函數時,編譯器生成默認的構造函數,這個函數針對內置類型不做處理,針對自定義類型成員,會去調用該類型的構造函數(而對于成員變量的聲明,可以給默認參數,本質上就是給這個自動生成的構造函數使用的

    • **默認構造函數(無參構造函數,全缺省構造函數,沒有構造函數時編譯器默認生成的構造函數)**最多只能有一個,也可以沒有(如果沒有,那就不能用默認方式初始化)如果當自己寫了別的不是默認構造函數形式的構造函數,那就需要自己在寫一個默認構造函數

    • 有兩種情況不需要自己寫構造函數:

      • 內置類型成員都有缺省值,且初始化符合我們的要求
      • 全是自定義類型的數據,且這些類型都有自己的默認構造函數
    • class stack {
      public:stack(int capacity=4) {_a = (int*)malloc(sizeof(int) * capacity);_capacity = 0;_top = 0;}private:/*給的是缺省值,是給編譯器的默認構造函數用的,這里并沒有開辟空間,在實例化的時候才會開辟空間*/int* _a=nullptr;int _capacity=1;int _top=1;
      };
      

  • 二.析構函數(相當于destroy)(完成對象中資源的清理工作,即free等,為了防止編譯器直接銷毀對象造成內存泄露):

    • 在類名前加上~

    • 無返回值無參數

    • 不可以重載

    • 編譯系統自動調用

    • 不寫析構函數,編譯器會自動生成(這個函數針對內置類型不做處理,針對自定義類型成員,會去調用該類型的析構函數)

    • 有動態申請的資源,就需要自己寫析構函數(因為普通的變量會在函數本身創建的棧上,隨函數結束棧的銷毀而銷毀了,所以只有在堆區或其他區上有自行申請的資源才需要析構)

    • class stack {
      public:~stack() {free(_a);_a = nullptr;_capacity = 0;_top = 0;}
      private:int* _a;int _capacity;int _top;
      };
      

  • 三.拷貝構造

    • 是一種構造函數的特殊重載形式,相當于傳一個同類型的變量作為參數

    • 在傳參時,必須以引用的方式傳遞參數,不然會發生無限遞歸

    • 因為如果以傳值調用來傳遞參數,本質上來說其實是要調用該類型的拷貝構造函數來創建形參的,也就相當于對于內置數據類型形參是直接拷貝,而自定義數據類型則是調用拷貝構造函數來創建形參的

    • class Date {
      public:Date(const Date & d) {_year = d._year;_mon = d._mon;_day = d._day ;}
      private:int _year = 1;int _mon = 1;int _day = 1;
      };
      
    • 雖然_year這些成員屬性是私有的,但私有屬性只有在類外不能訪問,此時在類內,是可以訪問的

    • 如果不顯式定義,編譯器會自己生成默認拷貝構造函數,默認是:

      • 內置數據類型完成值拷貝/淺拷貝
      • 自定義數據類型會調用它的拷貝構造函數
    • 在有些場景下,淺拷貝不足以滿足要求,就需要自己寫拷貝構造函數,以實現深拷貝(比如在stack里,如果進行淺拷貝,那么會使兩個棧里面的數組指針指向同一塊空間(因為淺拷貝只將數值原封不動的拷貝過去,所以它們指向同一塊空間),顯然不是我們想要的)


  • 四.賦值運算符重載

    • 用于已經存在的兩個對象之間的賦值拷貝

    • 本質就是將賦值運算符重載了一下

    • 如果不顯式定義,編譯器會自己生成默認賦值運算符重載,默認是:

        • 內置數據類型完成值拷貝/淺拷貝
        • 自定義數據類型會調用它的賦值運算符重載
      • 賦值運算符只能定義在類內部,不能重載成全局函數。(別的運算符既可以重載在類內,也可以重載成全局,但由于賦值運算符重載是一種默認成員函數,所以只能在類內)
    • class Date {
      public:Date& operator= (Date& x) {_day = x._day;return *this;}
      //之所以返回值是一個(Date&),是為了支持連續賦值的情景,如果不要求支持連續賦值,則返回值可以寫成void
      private:int _year = 1;int _mon = 1;int _day = 1;
      };int main() {Date d1(1);Date d2(2);Date d3(3);d3 = d1 = d2;return 0;
      }
      

  • 五.取地址運算符的重載

  • Date* Date::operator& () {return this;
    }
    const Date* Date::operator& () const {return this;
    }//這兩個函數因為參數不同構成函數重載
    

  • const

    • 對應一些成員實例,如果是const修飾的,那么在使用一些成員函數的時候可能會造成權限的放大,從而導致錯誤

    • 下面這個代碼里,如果print函數右側不加const,則無法正常打印,因為此時d1的類型是const Date ,而且指向該對象的指針this是隱式傳遞的,類型是Date* 由于它的類型是編譯器底層傳遞的,我們不能顯式來寫出this,所以只能將const寫在最右邊,其實本質就是修飾this指針的

    • void print() const//修飾this指針的const
      {cout << _year<<"--"<<_mon<<"--"<<_day << endl;
      }const Date d1(2023, 1, 26);
      d1.print();
      

在談構造函數
  • 第一種:構造函數體賦值

  • Date::Date(int year, int mon, int day) {_year = year;_mon = mon;_day = day;
    }
    
  • 第二種:初始化列表

    • 有三類成員變量必須用初始化列表初始化:
      • 沒有默認構造函數的結構體變量
      • 引用類型
      • const修飾的變量
    • 對于初始化列表的理解:在實例化對象時相當于時整個對象的定義,而對于它的成員變量,其實是在初始化列表所在的位置定義的,因為引用和const修飾的變量只有在定義的時候才能賦值,所以它們只能在初始化列表里面初始化。其實在初始化列表里,如果不寫出所有成員變量,那么就是自定義類型調用默認構造函數,內置類型不做處理(其實內置類型的成員變量在聲明的時候給的默認值,就是傳到初始化列表里,用于內置類型成員變量初始化的。)它下面的那個{},是為了某些多步初始化的過程無法在初始化列表里完成,需要在{}里完成
    • 成員變量的初始化順序是按類中的聲明順序初始化的,和其在初始化列表里的順序無關
  • Date(int year, int mon, int day):_year(year), _mon(mon), _day(day)
    {}
    

explicit 關鍵字
  • 如果構造函數在傳參的時候不想讓其發生隱式類型轉換,就可以在函數名之前加上explicit

靜態成員,函數
  • 靜態成員變量是屬于這個類的,生命周期是全局的。而普通的成員變量是屬于該類的實例的。也就是說靜態成員變量是所有實例共享的變量。
  • 靜態成員變量沒有初始化列表,所以靜態成員變量必須在類外邊,全局位置定義。(本質上相當于用類去封裝全局變量)
  • 靜態成員函數:沒有this指針,只要指定類域和訪問限定符即可訪問。靜態成員函數只能訪問靜態成員變量,因為它沒有this指針,沒法訪問某一個實例的普通成員變量
  • 非靜態函數可以訪問靜態成員變量,靜態函數不可以訪問靜態成員變量,函數(因為靜態函數沒有this指針)
class A {
public:static int _a;
private:
};int A::_a = 0;int main() {A aa;cout << ++A::_a << endl;cout << A::_a << endl;return 0;
}
-------------------------------------------------------------
-------------------------------------------------------------   
class A {
public:static int Get() {return _a;}
private:static int _a;
};int A::_a = 0;int main() {A aa;cout << aa.Get() << endl;cout << A::Get() << endl;return 0;
}

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

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

相關文章

極狐GitLab 如何撤銷變更?

極狐GitLab 是 GitLab 在中國的發行版&#xff0c;關于中文參考文檔和資料有&#xff1a; 極狐GitLab 中文文檔極狐GitLab 中文論壇極狐GitLab 官網 還原更改 (BASIC ALL) 在極狐GitLab 中&#xff0c;您可以還原單個提交或整個合并請求。 當您在 Git 中還原一個提交時&…

PNG透明免摳設計素材大全26000+

在當今的數字設計領域&#xff0c;尋找高質量且易于使用的素材是每個設計師的日常需求。今天&#xff0c;我們將為大家介紹一個超全面的PNG透明免摳設計素材大全&#xff0c;涵蓋多種風格、主題和應用場景&#xff0c;無論是平面設計、網頁設計還是多媒體制作&#xff0c;都能輕…

uniapp小程序使用echarts

1、引入插件 在Dcloud插件市場下載echarts插件&#xff1a;插件地址 2、頁面使用簡單示例&#xff1a; <template><view class"pie-view flex-center"><view style"width: 100%; height: 600rpx"><l-echart ref"chartRef&quo…

7-1 三種語言的單詞轉換

編寫程序實現&#xff1a;首先從鍵盤輸入若干個中文與英文單詞的偶對&#xff0c;以空行作結束標記&#xff1b;再輸入若干個英文與丹麥文單詞的偶對&#xff0c;以空行作結束標記。然后輸入一個中文單詞&#xff0c;輸出對應的丹麥文單詞&#xff1b;若不存在該單詞&#xff0…

開源AI守護童心——幼兒跌倒報警系統的智能安全革命

幼兒園是孩子們成長的樂園&#xff0c;但跌倒事件卻時常讓家長和園方憂心。教室、走廊、操場&#xff0c;幼兒的每一次意外跌倒都可能帶來安全隱患。傳統人工監管難以全天候覆蓋&#xff0c;反應速度也常受限。如何讓幼兒園更安全、更放心&#xff1f;幼兒跌倒報警系統&#xf…

Halcon應用:相機標定

提示&#xff1a;若沒有查找的算子&#xff0c;可以評論區留言&#xff0c;會盡快更新 Halcon應用&#xff1a;相機標定 前言一、Halcon應用&#xff1f;二、應用實戰1、圖像理解1.1、開始標定 前言 本篇博文主要用于記錄學習Halcon中算子的應用場景&#xff0c;及其使用代碼和…

Arduino示例代碼講解:Project 08 - Digital Hourglass 數字沙漏

Arduino示例代碼講解:Project 08 - Digital Hourglass 數字沙漏 Project 08 - Digital Hourglass 數字沙漏程序功能概述功能:硬件要求:輸出:代碼結構全局變量`setup()` 函數`loop()` 函數計時和點亮LED:讀取傾斜開關狀態:重置LED和計時器:運行過程注意事項Project 08 - …

《計算機視覺度量:從特征描述到深度學習》—深度學習圖像特征工程

傳統算法的圖像特征分析和描述&#xff0c;一直貫穿圖像算法的發展。2017年深度學習的出現&#xff0c;很多開發人員和技術人員認為&#xff0c;圖像特征分析這個概念可以被深度學習完全取代。很長一段時間以深度學習為主的視覺方案成為主流&#xff0c;逐漸淡化了傳統視覺的特…

零部件三維激光掃描檢測

制造業競爭激烈&#xff0c;零部件的精準檢測與三維數據的高效獲取&#xff0c;已成為企業確保產品質量、提升生產效率的核心要素。傳統檢測手段&#xff0c;往往因效率低下、精度不足&#xff0c;難以滿足復雜零部件的檢測需求。 傳統零部件檢測&#xff0c;檢測人員通常是手…

KafkaSpark

Kafka Kafka基本概念 卡夫卡是一個分布式、分布訂閱的消息系統&#xff0c;作為消息中間件使用。 設計上是一個分布式的、分區的和可復制的提交日志服務。 Kafka的優勢 分布式系統&#xff0c;易于擴展。 高吞吐量&#xff0c;支持發布和訂閱模式。 支持多地復制&#xff…

圖文結合 - 光伏系統產品設計PRD文檔 -(慧哥)慧知開源充電樁平臺

光伏系統產品設計PRD文檔 ?版本號?&#xff1a;1.0 ?修訂日期?&#xff1a;2023年10月 ?作者?&#xff1a; 一、文檔概述 1.1 背景與目標 ?行業背景?&#xff1a;全球光伏裝機量年增長20%&#xff0c;數字化運維需求迫切?用戶痛點?&#xff1a;現有系統存在數據延…

Eyecare-100K:首個覆蓋多模態、多任務的高質量眼科視覺指令數據集

2025-04-18 , 由浙江大學、哈爾濱工業大學、郴州市第一人民醫院、新加坡國立大學等機構合作創建了 Eyecare-100K數據集&#xff0c;這是首個涵蓋多種模態、任務和疾病的高質量眼科視覺指令數據集&#xff0c;為眼科智能診斷領域提供了關鍵資源&#xff0c;推動了醫學視覺語言模…

CoT-Drive:利用 LLM 和思維鏈提示實現自動駕駛的高效運動預測

25年3月來自澳門大學和 MIT 的論文“CoT-Drive: Efficient Motion Forecasting for Autonomous Driving with LLMs and Chain-of-Thought Prompting”。 準確的運動預測對于安全的自動駕駛 (AD) 至關重要。本研究提出 CoT-Drive&#xff0c;這是一種利用大語言模型 (LLM) 和思…

[FPGA基礎] RAM篇

Xilinx FPGA RAM 使用指南 1. 引言 隨機存取存儲器&#xff08;RAM&#xff09;是 Xilinx FPGA 設計中用于存儲和快速訪問數據的重要資源。Xilinx FPGA 提供多種 RAM 類型&#xff0c;包括塊 RAM&#xff08;Block RAM&#xff09;和分布式 RAM&#xff08;Distributed RAM&a…

Elasticsearch內核探秘:從Shard分配到網絡通信的深度實踐指南

#作者&#xff1a;孫德新 文章目錄 一、底層模塊深入解析之shard allocation1、shard allocation的介紹2、cluster level shard allocation介紹3、disk-based shard allocation介紹4、shard allocation awareness5、shard allocation filtering6、node下線時的shard延遲分配7、…

SQL Server 2022 常見問題解答:從安裝到優化的全場景指南

SQL Server 2022 作為微軟最新的數據庫管理系統&#xff0c;在性能、安全性和云集成方面帶來了多項革新。然而&#xff0c;用戶在實際使用中仍可能遇到各類問題。本文將圍繞安裝配置、性能優化、備份恢復、安全設置、高可用性方案、兼容性問題及錯誤代碼解析等核心場景&#xf…

57、Spring Boot 最佳實踐

Spring Boot 最佳實踐 一. 開發規范與代碼風格 編寫高質量的代碼不僅需要功能的實現,還需要遵循一定的規范和代碼風格,以提高代碼的可讀性、可維護性和協作效率。以下是 Spring Boot 開發中的一些關鍵規范和代碼風格建議。 1. 代碼命名規范 在編寫代碼時,命名是非常重要的…

??OSPF核心機制精要:選路、防環與設計原理?

一、OSPF選路規則解析 OSPF作為經典的鏈路狀態路由協議&#xff0c;其選路規則采用層次化優先級機制&#xff0c;不同路由類型遵循嚴格比較順序&#xff1a; 1. 路由類型優先級 優先級路由類型描述1域內路由通過1類、2類LSA生成2域間路由通過3類LSA生成3域外路由通過5類/7類…

1.1軟考系統架構設計師:系統架構的定義與作用 - 超簡記憶要點、知識體系全解、考點深度解析、真題訓練附答案及解析

超簡記憶要點 定義&#xff1a;結構決策 | 抽象概念 | 多視圖模型&#xff08;邏輯/物理/動態&#xff09;作用&#xff1a;解耦復雜需求 | 集成擴展 | 指導開發&#xff08;藍圖&#xff09;要素&#xff1a;構件&#xff08;原子/復合&#xff09; | 連接件&#xff08;API/…

網絡socks 代理

在系統/終端中設了這樣的環境變量&#xff0c;而沒有在代碼中覆蓋&#xff0c;HTTPX 就會啟用該 socks 代理。 env | grep proxy https_proxyhttps://proxyhk.zte.com.cn:80 http_proxyhttp://proxyhk.zte.com.cn:80 no_proxylocalhost,127.0.0.0/8,::1,zte.com.cn,zte.intra,…