亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++的構造函數和析構函數是什么

發布時間:2021-06-30 17:07:49 來源:億速云 閱讀:214 作者:chen 欄目:開發技術

本篇內容主要講解“C++的構造函數和析構函數是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C++的構造函數和析構函數是什么”吧!

目錄
  • 一、構造函數

  • 二、C++類的內存模型

    • 2.1、只定義成員函數

    • 2.2、往空類中添加靜態成員變量

    • 2.3、再加入非靜態成員變量

  • 三、this指針

    • 四、析構函數

      一、構造函數

      首先,由于類只是一個模板,因此我們在定義類時無法對成員變量初始化,比如下面代碼就是錯誤的:

      class circle{
      public:
          int m_L = 20;	// Error:不允許使用數據成員初始值設定項
      };

      因此,初始化只能發生在類創建對象的過程中,但是由于訪問權限的原因,無法在類外訪問某些成員變量,因此下面這種做法有時候是無效的:

      circle C1;	// 實例化一個對象 C1
      C1.m_L = 20;	// 通過創建的對象,來給對應變量初始化,但是如果m_L是private訪問權限,則失效

      為了解決這個問題,讓程序員能像使用標準數據類型一樣適用對象,在類內提供了一個特殊的成員函數——“構造函數”,專門用于在創建對象時初始化類對象。之所以說它特殊,是因為C++已經自動為構造函數提供了名稱和使用語法,程序員只需要提供方法的定義即可,即:類名(形參列表)。具體來說,構造函數的定義如下:

      class circle{
      public:
          int m_L;
      public: //成員函數(方法)
          circle(const int a)	//通過構造函數對成員變量進行賦值
          {
              m_L = a;
          }
      };
      
      circle C1(20);	//調用格式
      cout << "C1.m_L:" << C1.m_L <<endl;

      看上去似乎很簡單,但是由于構造函數也是函數,因此所有C++中的形參傳遞方式,函數特性以及函數調用方法都能用于構造函數。 如前文所講,C++會自動給類添加一個空的構造函數,但是如果自己在類中實現了有參構造函數,編譯器便不再提供無參構造函數。舉例如下:

      class circle{
      public:
          int m_L;
      public: //成員函數(方法)
          circle(const int a)	//通過構造函數對成員變量進行賦值
          {
              m_L = a;
          }
      };
      
      circle C1(20);	//調用格式正確,能夠通過構造函數賦值
      circle C2; 		//錯誤,自己定義了有參構造函數,不再提供無參構造函數

      構造函數可以重載,接著上面的例子,如果重載一個空的構造函數,那么兩個調用格式都正確:

      class circle{
      public:
          int m_L;
      public: //成員函數(方法)
          circle(){}	// 空構造函數
          circle(const int a)	//通過構造函數對成員變量進行賦值
          {
              m_L = a;
          }
      };
      
      circle C1(20);	//調用格式正確,能夠通過構造函數賦值
      circle C2; 		//正確,可以通過重載的空構造函數實現初始化

      構造函數的參數不僅可以是標準數據類型,也可以是類。眾所周知,在數值作為函數參數進行傳遞的時候,會重新拷貝出來一份數據作為參數傳遞用完即銷毀,這種方式不僅浪費了內存空間,而且無法修改原始數據。為了結合這兩者之間的優點,于是經常采取引用作為函數的參數。雖然引用是指針的一種特殊情況,但是指針太過于靈活,并且引用在形式上引用與普通的變量地用法并沒有什么區別,因此使用起來更加方便。

      class circle{
      public:
          int m_L;
      public: //成員函數(方法)
          circle(){}	// 空構造函數
          circle(const int a)	//通過構造函數對成員變量進行賦值
          {
              m_L = a;
          }
          //引用作為函數參數傳遞,并用const修飾,節省空間的同時避免修改原數據
          circle(const circle& sub_circle)	
          {
              m_L = sub_circle.m_L;
          }
      };
      
      circle C1(20);	//調用格式正確,能夠通過構造函數賦值
      circle C2(C1); 	//正確,可以通過拷貝構造函數進行初始化

      二、C++類的內存模型

      C++中,一個類包括:

      • 成員變量:靜態成員變量和普通成員變量

      • 成員函數:靜態成員函數和普通成員函數

      雖然為了集成,我們將其寫到一個類里面,但是只有普通成員變量真正屬于類的對象,類的所有對象共享一份靜態成員函數,靜態成員變量和普通成員函數。畫出了內存模型,如下圖所示:

      C++的構造函數和析構函數是什么

      為了進一步理解,我們舉例如下:

      2.1、只定義成員函數

      class person{
      public:
          // 定義一個空的構造函數
      	person(int m_age, int m_ID){
      	}
      };
      person p1(10, 20);
      cout << "p1 所占的空間為:" << sizeof(p1) << endl;

      輸出結果為:

      p1 所占的空間為:1

      這個題目在《劍指offer》一書中也提到過,由空類實例化出來的對象所占的內存空間是1個而不是0個字節,因為編譯其給對象 p1 分配了一個地址,來表示不同的對象存儲在不同的地址空間,因此占用1個字節。

      2.2、往空類中添加靜態成員變量

      class person{
          static int age; //靜態成員變量,存在全局區,不屬于類對象的一部分
          static int ID;  //靜態成員變量,存在全局區,不屬于類對象的一部分
      public:
          // 定義一個空的構造函數
      	person(int m_age, int m_ID){
      	}
      };
      person p1(10, 20);
      cout << "p1 所占的空間為:" << sizeof(p1) << endl;

      輸出結果為:

      p1 所占的空間為:1

      當向類中加入了成員函數與靜態成員變量時,類的實例化對象仍然只占用1個字節的空間,足以證明這些函數和變量并不是類對象的一部分。

      2.3、再加入非靜態成員變量

      class person
      {
          static int age; //靜態成員變量,存在全局區,不屬于類對象的一部分
          static int ID;  //靜態成員變量,存在全局區,不屬于類對象的一部分
          int a;	//非靜態成員變量,存在棧區,屬于類對象的一部分
      public:
      	person(int m_age, int m_ID){
      	}
      };

      輸出結果為:

      p 所占的空間為:4

      因此當向類中加入了非靜態成員變量時,類的實例化對象占用4個字節的空間,可以說明,非靜態變量屬于類對象的一部分。綜上:同一個類所有實例化出來的對象共享同一份靜態成員變量,所以一改全改。既然同一個類的不同對象共享同一份成員函數,那么成員函數怎么區分該訪問哪個對象的普通成員變量呢?

      三、this指針

      接著上一小節的問題,this指針為上述問題提供了一個完美的解決方案,它指向用來調用成員函數的對象(被當作參數隱式地傳遞給成員函數),我們通過一張圖來理解它:

      C++的構造函數和析構函數是什么

      此外,this指針的另一個用途是當成員函數需要返回對象時,用 return *this; 或者 return this,這種做法能夠實現鏈式編程。比如:

      p2.addPerson(p1).addPerson(p1);

      首先,對象 p2 調用成員函數 addPerson(p1) ,其返回值繼續調用 addPerson(p1),此時返回值就必須也是 person 類型才可以,因此使用 this 指針可以完成需求。先來看第一個例子:

      class person{
      public:
      	int age;
      	person(int age)
      	{
      		this->age = age; // this指針區分調用者
      	}
      	// 返回值為person類型,且參數加上了const限制,防止修改原數據
      	person addPerson(const person& p)
      	{
      		this->age += p.age;	// 主要實現兩個類對象年齡的相加
      		return *this;	// 由于返回值是person,因此返回 *this
      	}
      };
      
      person p1(20);
      person p2(10);
      person p3 = p2.addPerson(p1).addPerson(p1);
      cout << "p1 age:" << p1.age << endl;
      cout << "p2 age:" << p2.age << endl;
      cout << "p3 age:" << p3.age << endl;

      首先,通過構造函數分別對 p1,p2 賦了初值,然后 p2 調用函數 addPerson(p1) 修改自身的變量 age 。**由于函數通過值傳遞的方式返回 person 類型,所以將整個 person 類型復制了一份返回,返回值繼續調用 addPerson(p1), **最后的結果賦值給了新的對象 p3。所以輸出結果為:

      p1 age:20

      p2 age:30

      p3 age:50

      但是如果函數 addPerson() 修改為:

      person& addPerson(const person& p)
      {
          this->age += p.age;	// 主要實現兩個類對象年齡的相加
          return *this;	// 雖然返回值是person&,返回值的類型也是 *this
      }
      
      person p1(20);
      person p2(10);
      person p3 = p2.addPerson(p1).addPerson(p1);
      cout << "p1 age:" << p1.age << endl;
      cout << "p2 age:" << p2.age << endl;
      cout << "p3 age:" << p3.age << endl;

      與上例唯一的區別就在于返回值的類型變成了引用,那么每次返回的就變成了該對象本身,而非在值傳遞中拷貝出來的那一份數據。那么輸出就變成了:

      p1 age:20

      p2 age:50

      p3 age:50

      四、析構函數

      用構造函數創建對象后,程序負責跟蹤該對象,知道其過期為止。當對象過期時,程序自動調用析構函數完成清理工作。與構造函數一樣,C++默認提供了一個空的析構函數,定義為:~類名( )。由于開辟在棧區的變量程序會自動釋放,因此不需要析構函數執行清理工作,但是當程序員在堆區開辟空間時,需要手動執行清理工作,這時候需要析構函數來釋放堆區內存。比如:

      ~person()
      {
      	// 在析構函數內寫入需要執行的代碼
      	cout << "調用析構函數" << endl;
      }
      person p1(20);
      person p2(10);	// 在生命周期結束后自動調用析構函數執行清理工作

      輸出為:

      調用析構函數

      調用析構函數

      到此,相信大家對“C++的構造函數和析構函數是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

      向AI問一下細節

      免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

      c++
      AI

      肇州县| 兴国县| 民丰县| 林口县| 镇原县| 永仁县| 松溪县| 周至县| 岢岚县| 平邑县| 琼结县| 吉安市| 赤壁市| 广南县| 盱眙县| 泗水县| 武宣县| 资源县| 葫芦岛市| 陆河县| 通河县| 岱山县| 石城县| 沂南县| 依安县| 汉阴县| 新化县| 梨树县| 岫岩| 醴陵市| 济南市| 玉龙| 信阳市| 沭阳县| 两当县| 湖北省| 朝阳市| 花垣县| 达孜县| 齐齐哈尔市| 西贡区|