C++初階——類和對象(三) 構造函數、析構函數

C++初階——類和對象(三)

上期內容,我們圍繞類對象模型的大小計算成員存儲方式this指針,以及C++實現棧和C語言的比較,進一步認識了C++的封裝特性。本期內容,我們開始介紹類的默認成員函數,這是類和對象板塊中最為重要,也是相對復雜的內容,讓我們一起探索!

引言

如果一個類中什么成員都沒有,簡稱為空類。空類中真的什么都沒有嗎?并不是,任何類在什么都不寫時,編譯器會自動生成以下6個默認成員函數(默認成員函數:用戶沒有顯式實現,編譯器會生成的成員函數稱為默認成員函數):

  • 初始化和清理:構造函數析構函數
  • 拷貝復制:拷貝構造函數賦值重載函數
  • 取地址重載:普通對象取地址重載const對象取地址重載函數

一、構造函數

1.背景引入

示例1
示例2

我們再來回顧一下,_year_month_day是三個私有的成員變量,InitPrint是外界可以直接訪問的成員函數,在main函數中,我們先要通過類來示例化出一個對象,比如這里的Date d1; Date d2; Date d3;等等,然后調用類里面的成員函數。這里基于同一個類創建了很多對象,然而在成員函數中似乎并沒有傳遞代表各個對象的形參,那么編譯器是怎么區分的呢?很簡單,由于this指針的存在。我們以d1.Init(2025,3,10);為例,this指針指向當前的對象——d1,然后在調用函數Init時,隱式傳遞了這個指針,然后通過這個指針訪問d1中的成員變量_year、_month、_day,將它們分別賦值為2025、3、10,如圖所示:
示例3
當運行到下一個對象d2時,this指針指向的就是d2了。

進一步探究

如果我們仔細觀察,不難發現這里分為了兩步走:第一步,先通過類實例化一個對象,也就是Date d1;,然后再用具體的數值將其初始化d1.Init(2025,3,10);,其實是有些麻煩的,我們能不能在實例化對象的同時,就將信息設置進去呢?——答案是肯定的,C++本身就是對C語言的優化,構造函數應運而生!

2.什么是構造函數?

構造函數是一個特殊的成員函數,名字與類名相同。創建類對象時由編譯器自動調用,以保證每個數據成員都有一個合適的初始值,并且在對象整個生命周期內只調用一次
示例4
示例5
在這里,我們已經將原來的初始化函數改造成了一個構造函數,構造函數的函數名與類名相同,沒有返回值(這里的沒有返回值不是說返回一個void,寫成void Date(int year, int month, int day),而是什么都不要寫,直接就是Date(int year, int month, int day)),至于為什么,這是語法規定,這是一個特殊的函數,有特殊的待遇,只有這樣寫,編譯器才知道這是構造函數。對于構造函數的調用,也是很有趣的,我們在實例化對象的同時,后面跟上了一個括號,里面就是想要在對象中填入的信息Date d1(2025, 3, 10);,這樣一來,我們不僅實例化了一個對象,還填入了我們想要的信息,一步解決,非常方便。之前的那種兩步走,是先根據圖紙建房子,然后里面的家具還要自己來置辦;現在是把裝修也一并讓別人做好了,自己直接拎包入住,確實方便的多。

3.構造函數的特性

構造函數是特殊的成員函數,需要注意的是,構造函數雖然名稱叫構造,但是構造函數的主要任務并不是開空間創建對象,而是初始化對象。也很好理解,之前是兩步走,現在是一步走,至于減少的那一步——填入想要的信息,就是構造函數的功勞。

(1)構造函數的重載

構造函數是可以重載的,根據傳參的不同,調用對應的構造函數,如圖所示:
示例7
這里就寫了兩個構造函數,其中一個是無參數的,這些都可以理解,但是,我們注意到,為什么在調用的時候寫的是Date d1;而不是Date d1();呢?我們先來看一下結果:
示例8
這里什么都沒有輸出,也就是沒有調用那個構造函數,這是為什么呢?仔細觀察我們發現,Date d1();像是函數的聲明,Date返回值的類型d1函數名,()表示這個函數不需要傳參。基于這種情況,編譯器不知道這里到底是在類實例化對象還是在聲明一個名為d1的函數。因此,我們對于無參的構造函數,在實例化對象時就不需要加()
當然,還有一點,一開始的構造函數示例中,是提供了缺省參數的,而且是全缺省,這里做出了改變。如果依然是全缺省會發生什么呢?如圖所示:
示例9
示例10
還是一個調用不明確的問題:不傳參,不僅無參的函數可以調用,全缺省的也可以調用,因為它可以自動幫你把數據補上。在C++入門中已經講過這一點,這里就當是復習一下吧。

(2)默認構造函數
默認構造函數的分類

默認構造函數是無需參數即可調用的構造函數,我們既可以顯式聲明,也可以讓編譯器隱式生成。無參構造函數全缺省構造函數我們沒寫編譯器默認生成的構造函數,都可以認為是默認構造函數,再簡單一點,不需要傳參就可以調用的構造函數都是默認構造函數:

  • 無參構造函數
    示例11
  • 全缺省構造函數
    示例12
  • 編譯器默認生成的構造函數
    示例13
編譯器自動生成的構造函數

如果類中沒有顯式定義構造函數,則C++編譯器會自動生成一個無參的默認構造函數,一旦用戶顯式定義編譯器將不再生成。注意,這里是無參的,也就是說調用的時候直接寫Date d1;即可,如圖所示:
示例14
示例15
這里的默認構造函數似乎沒什么用,對于這些變量的值,好像也沒有進行處理,依舊是隨機值,那么默認構造函數還有它存在的價值嗎?
其實是這樣的:C++把類型分成內置類型(基本類型)和自定義類型。內置類型就是語言提供的數據類型,如:int、char、double……,自定義類型就是需要自己定義的,如struct、class……
編譯器生成的默認構造函數對內置類型不作處理對自定義類型則是調用它的默認構造。因此,一般情況下,有內置類型成員,就需要自己寫構造函數,不能用編譯器自己生成的;全部都是自定義類型成員,可以考慮讓編譯器自己生成。
我們來舉個自定義類型的例子:
示例16
在Date類的成員變量中,不僅有內置類型,還有自定義類型變量Time _t;那么在實例化對象時,內置類型不作處理自定義類型調用它的默認構造,而Time類的默認構造我們已經自己定義了,因此會打印出對應的結果,我們也可以調試看一看:
示例17
由于Date類中沒有自己寫構造函數,內置類型都是隨機值,而自定義類型Time _t就調用了它的默認構造,而Time的默認構造是我們自己實現的,對內置類型進行了初始化。

  • C++11 中針對內置類型成員不初始化的缺陷,又打了補丁,即:內置類型成員變量在類中聲明時可以給默認值:
    示例18
    這里沒有自己寫構造函數,默認值給在成員變量的聲明里。

二、析構函數

析構函數是特殊的成員函數,其特征如下:

  • 析構函數名是在類名前加上字符 ~。
  • 無參數無返回值類型。
  • 一個類只能有一個析構函數。若未顯式定義,系統會自動生成默認的析構函數。注意:析構函數不能重載
  • 對象生命周期結束時,C++編譯系統系統自動調用析構函數。

1.自己定義的析構函數

我們以一個為例,因為棧中涉及到動態內存開辟,不使用了需要及時銷毀開辟的內存空間,否則會造成內存泄漏,有了析構函數,我們只需要在類中定義一下,在類外它就會自動調用了,代碼如下:

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc fail");return;}_capacity = capacity;_size = 0;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}// 其他方法...~Stack(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}cout << "~Stack" << endl;}
private:DataType* _array;int _capacity;int _size;
};int main()
{Stack st1;return 0;
}

運行結果如圖:
示例19

2.編譯器自動生成的析構函數

關于編譯器自動生成的析構函數,是否會完成一些事情呢?下面的程序我們會看到,編譯器生成的默認析構函數,對自定類型成員調用它的析構函數。
示例20
如果類中沒有申請資源時,析構函數可以不寫,直接使用編譯器生成的默認析構函數,比如Date類;有資源申請時,一定要寫,否則會造成資源泄漏,比如Stack類。

本期總結+下期預告

本期內容非常重要,詳細介紹了類的構造函數和析構函數,下期將繼續講解拷貝構造函數等相關內容!

感謝大家的關注,我們下期再見!
在這里插入圖片描述

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

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

相關文章

【NLP】 5. Word Analogy Task(詞類比任務)與 Intrinsic Metric(內在度量)

Word Analogy Task&#xff08;詞類比任務&#xff09; 定義&#xff1a;Word Analogy Task 是用于評估詞向量質量的內在指標&#xff08;Intrinsic Metric&#xff09;。該任務基于這樣的假設&#xff1a;如果詞向量能夠捕捉單詞之間的語義關系&#xff0c;那么這些關系應該能…

矩陣冪(矩陣k次冪)

矩陣冪 #include<stdio.h> //矩陣乘法 void cf(int a[20][20],int b[20][20],int result[20][20],int n){for(int i0;i<n;i){for(int j0;j<n;j){result[i][j]0;for(int k0;k<n;k){result[i][j]a[i][k]*b[k][j];}}} }void print(int a[20][20],int n){for(int…

信火一體作戰模式運用特點分析及對一體化防空反導能力建設的啟示

文章目錄 內容摘要1. 引言2. 信火一體作戰模式在現代戰爭中的新內涵和特征2.1 充當火力和信息要素的作戰單元種類更加豐富2.2 信息利用更加凸顯異構平臺間的數據共享和情報融合2.3 作戰環節上更加強調指揮決策的敏捷性和智能化3. 增強防空反導能力的舉措建議3.1 強化各類作戰單…

樣本是怎么估計總體的

樣本是怎么估計總體的 flyfish 1. 什么是樣本估計總體&#xff1f; 樣本估計總體是指通過樣本數據&#xff08;例如100人的身高&#xff09;推斷總體參數&#xff08;例如全國人口的平均身高&#xff09;。核心方法包括&#xff1a; 點估計&#xff1a;用樣本統計量直接估計…

自己動手打造AI Agent:基于DeepSeek-R1+websearch從零構建自己的Manus深度探索智能體AI-Research

第一章&#xff1a;AI Agent基礎與DeepSeek-R1架構解析&#xff08;1/10&#xff09; 1.1 AI Agent技術演進與核心價值 人工智能代理&#xff08;AI Agent&#xff09;經歷了從規則驅動到數據驅動的范式轉移。早期基于專家系統的符號主義方法&#xff08;如MYCIN醫療診斷系統…

DeepSeek 助力 Vue3 開發:打造絲滑的表格(Table)之添加列寬調整功能,示例Table14_13可展開行的固定表頭表格

前言:哈嘍,大家好,今天給大家分享一篇文章!并提供具體代碼幫助大家深入理解,徹底掌握!創作不易,如果能幫助到大家或者給大家一些靈感和啟發,歡迎收藏+關注哦 ?? 目錄 DeepSeek 助力 Vue3 開發:打造絲滑的表格(Table)之添加列寬調整功能,示例Table14_13可展開行的固…

Gemini Robotics:將人工智能帶入物理世界

25年3月來自谷歌的技術報告“Gemini Robotics: Bringing AI into the Physical World”。 大型多模態模型的最新進展&#xff0c;已使數字領域出現卓越的通才能力&#xff0c;但將其轉化為機器人等物理智體仍然是一項重大挑戰。一般有用的機器人需要能夠理解周圍的物理世界&am…

關于離子濾波小記

粒子濾波&#xff08;Particle Filter, PF&#xff09; 粒子濾波是一種基于蒙特卡洛方法的貝葉斯濾波算法&#xff0c;主要用于解決非線性、非高斯的狀態估計問題。它廣泛應用于機器人定位、目標跟蹤、金融建模等領域。 1. 粒子濾波的基本概念 粒子濾波的核心思想是用一組加權…

機器語言基礎

機器語言是計算機能夠直接識別和執行的二進制代碼語言&#xff0c;由0和1組成。以下是關于機器語言的基本介紹&#xff1a; 特點 - 執行效率高&#xff1a;是計算機硬件直接支持的語言&#xff0c;無需翻譯&#xff0c;執行速度快&#xff0c;能充分發揮計算機的性能。 - 硬…

生活中的可靠性小案例11:窗戶把手斷裂

窗戶把手又斷了&#xff0c;之前也斷過一次&#xff0c;使用次數并沒有特別多。上方的圖是正常的把手狀態&#xff0c;斷的形狀如下方圖所示。 這種懸臂梁結構&#xff0c;沒有一個良好的圓角過渡&#xff0c;導致應力集中。窗戶的開關&#xff0c;對應的是把手的推拉&#xff…

多元時間序列預測的范式革命:從數據異質性到基準重構

本推文介紹了一篇來自中國科學院計算技術研究所等機構的論文《Exploring Progress in Multivariate Time Series Forecasting: Comprehensive Benchmarking and Heterogeneity Analysis》&#xff0c;發表在《IEEE Transactions on Intelligent Transportation Systems》。論文…

印章/公章識別:PaddleX下的“Seal-Recognition”模型

最近做項目需要對印章進行識別&#xff0c;并提取其中的印章文字&#xff0c;又不希望這個模型太大&#xff0c;還要方便部署&#xff0c;于是乎這個模型是個不錯的選擇。 一、模型簡介 “Seal-Recognition”模型是PaddleX旗下的一款模型&#xff08;PaddleX 是基于飛槳框架構…

An effective algorithm for peptide de novo sequencing from MS/MS spectra

1. 研究背景 數據庫搜索方法 需要已知的蛋白數據庫&#xff0c;但對于未知蛋白質&#xff0c;無法適用。de novo 測序方法 直接從 MS/MS 數據推斷氨基酸序列&#xff0c;非常重要。 2. 現有方法的問題 暴力搜索方法&#xff1a;枚舉所有可能的肽序列并與 MS/MS 數據比對&…

算法專題一:雙指針

1.移動零 題目鏈接&#xff1a;283. 移動零 - 力扣&#xff08;LeetCode&#xff09; 我們可以定義一個dest&#xff0c;一個cur&#xff0c;dest表示數組中不為零的數的最后一位&#xff0c;cur用來遍歷數組 class Solution {public void moveZeroes(int[] nums) {for(int cur…

【大模型實戰】利用ms-swift微調框架對QwQ-32B推理模型進行微調

1. 背景介紹 之前我們在《大模型訓練/微調的一些經驗分享》、《利用DeepSeek-R1數據微調蒸餾ChatGLM32B讓大模型具備思考能力》中做了相關模型微調的介紹。目前在基座大模型能力還沒有達到足夠牛的情況下&#xff0c;大模型微調在商業化、垂直領域應用依然是不可或缺&#xff0…

【Unity3D】Addressables使用流程

Package Manager - 搜索 Addressables 安裝 Window -> Asset Management -> Addressables 打開窗口 New -> 新建Packed Assets 資源組 默認資源組Default xxx (Default) 將資源&#xff0c;如預制體直接拖拽進資源組 Build -> New Build -> Default Buil…

k8s serviceaccount在集群內指定apiserver時驗證錯誤的問題

在主機上&#xff0c;找到TOKEN&#xff0c;可以直接指定apiserver使用 rootubuntu-server:/home# kubectl auth can-i --list --server https://192.168.85.198:6443 --token"eyJhbGciOiJSUzI1NiIsImtpZCI6IlFlMHQ3TzhpcGw1SnRqbkYtOC1NUWlWNUpWdGo5SGRXeTBvZU9ib25iZD…

Linux驅動開發-①pinctrl 和 gpio 子系統②并發和競爭③內核定時器

Linux驅動開發-①pinctrl 和 gpio 子系統②并發和競爭③內核定時器 一&#xff0c;pinctrl 和 gpio 子系統1.pinctrl子系統2.GPIO子系統 二&#xff0c;并發和競爭1.原子操作2.自旋鎖3.信號量4.互斥體 三&#xff0c;按鍵實驗四&#xff0c;內核定時器1.關于定時器的有關概念1.…

數據庫的高階知識

目錄 一、case when二、幾種常見的嵌套查詢2.1 比較運算符2.2 ANY/ALL 關鍵詞2.3 in 關鍵詞2.4 EXISTS關鍵詞2.5 in和exists的異同點 三、開窗函數 數據庫的基本知識 數據庫的高階知識 一、case when 在實際工作中&#xff0c;經常會涉及以下兩類問題&#xff1a; 數據的映射…

【Kubernetes】Service 的類型有哪些?ClusterIP、NodePort 和 LoadBalancer 的區別?

在 Kubernetes 中&#xff0c;Service 是一種抽象的方式&#xff0c;用于將一組 Pod 進行連接并暴露給外部或集群內部訪問。它的主要目的是通過提供穩定的 IP 地址和端口來允許其他服務或客戶端與一組 Pod 進行通信。 Service 類型 Kubernetes 中 Service 有四種主要類型&…