欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

全面解析C++中的析構(gòu)函數(shù)

 更新時(shí)間:2016年01月22日 14:25:47   投稿:goldensun  
這篇文章主要介紹了C++中的析構(gòu)函數(shù),為C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下

“析構(gòu)函數(shù)”是構(gòu)造函數(shù)的反向函數(shù)。在銷毀(釋放)對(duì)象時(shí)將調(diào)用它們。通過(guò)在類名前面放置一個(gè)波形符 (~) 將函數(shù)指定為類的析構(gòu)函數(shù)。例如,聲明 String 類的析構(gòu)函數(shù):~String()。
在 /clr 編譯中,析構(gòu)函數(shù)在釋放托管和非托管資源方面發(fā)揮了特殊作用。
析構(gòu)函數(shù)通常用于在不再需要某個(gè)對(duì)象時(shí)“清理”此對(duì)象。請(qǐng)考慮 String 類的以下聲明:

// spec1_destructors.cpp
#include <string.h>

class String {
public:
  String( char *ch ); // Declare constructor
  ~String();      // and destructor.
private:
  char  *_text;
  size_t sizeOfText;
};

// Define the constructor.
String::String( char *ch ) {
  sizeOfText = strlen( ch ) + 1;

  // Dynamically allocate the correct amount of memory.
  _text = new char[ sizeOfText ];

  // If the allocation succeeds, copy the initialization string.
  if( _text )
   strcpy_s( _text, sizeOfText, ch );
}

// Define the destructor.
String::~String() {
  // Deallocate the memory that was previously reserved
  // for this string.
  if (_text)
   delete[] _text;
}

int main() {
  String str("The piper in the glen...");
}

在前面的示例中,析構(gòu)函數(shù) String::~String 使用 delete 運(yùn)算符來(lái)動(dòng)態(tài)釋放為文本存儲(chǔ)分配的空間。
聲明析構(gòu)函數(shù)
析構(gòu)函數(shù)是具有與類相同的名稱但前面是波形符 (~) 的函數(shù)
該語(yǔ)法的第一種形式用于在類聲明中聲明或定義的析構(gòu)函數(shù);第二種形式用于在類聲明的外部定義的析構(gòu)函數(shù)。
多個(gè)規(guī)則管理析構(gòu)函數(shù)的聲明。析構(gòu)函數(shù):

  • 不接受參數(shù)。
  • 無(wú)法指定任何返回類型(包括 void)。
  • 無(wú)法使用 return 語(yǔ)句返回值。
  • 無(wú)法聲明為 const、volatile 或 static。但是,可以為聲明為 const、volatile 或 static 的對(duì)象的析構(gòu)調(diào)用它們。
  • 可以聲明為 virtual。通過(guò)使用虛擬析構(gòu)函數(shù),無(wú)需知道對(duì)象的類型即可銷毀對(duì)象 - 使用虛函數(shù)機(jī)制調(diào)用該對(duì)象的正確析構(gòu)函數(shù)。請(qǐng)注意,析構(gòu)函數(shù)也可以聲明為抽象類的純虛函數(shù)。

使用構(gòu)造函數(shù)

當(dāng)下列事件之一發(fā)生時(shí),將調(diào)用析構(gòu)函數(shù):
使用 delete 運(yùn)算符顯式解除分配了使用 new 運(yùn)算符分配的對(duì)象。使用 delete 運(yùn)算符解除分配對(duì)象時(shí),將為“大多數(shù)派生對(duì)象”或?yàn)閷儆谕暾麑?duì)象,但不是表示基類的子對(duì)象的對(duì)象釋放內(nèi)存。此“大多數(shù)派生對(duì)象”解除分配一定僅對(duì)虛擬析構(gòu)函數(shù)有效。在類型信息與實(shí)際對(duì)象的基礎(chǔ)類型不匹配的多重繼承情況下,取消分配可能失敗。
具有塊范圍的本地(自動(dòng))對(duì)象超出范圍。
臨時(shí)對(duì)象的生存期結(jié)束。
程序結(jié)束,并且存在全局或靜態(tài)對(duì)象。
使用析構(gòu)函數(shù)的完全限定名顯式調(diào)用了析構(gòu)函數(shù)。(有關(guān)詳細(xì)信息,請(qǐng)參閱顯式析構(gòu)函數(shù)調(diào)用。)
前面的列表中所述的情況將確保所有對(duì)象均可通過(guò)用戶定義的方法進(jìn)行銷毀。
如果基類或數(shù)據(jù)成員有一個(gè)可訪問(wèn)的析構(gòu)函數(shù),并且派生類未聲明析構(gòu)函數(shù),則編譯器將生成一個(gè)析構(gòu)函數(shù)。此編譯器生成的析構(gòu)函數(shù)將為派生類型的成員調(diào)用基類析構(gòu)函數(shù)和析構(gòu)函數(shù)。默認(rèn)析構(gòu)函數(shù)是公共的。

析構(gòu)函數(shù)可以隨意調(diào)用類成員函數(shù)和訪問(wèn)類成員數(shù)據(jù)。從析構(gòu)函數(shù)調(diào)用虛函數(shù)時(shí),調(diào)用的函數(shù)是當(dāng)前正在銷毀的類的函數(shù)。
析構(gòu)的順序
當(dāng)對(duì)象超出范圍或被刪除時(shí),其完整析構(gòu)中的事件序列如下所示:
將調(diào)用該類的析構(gòu)函數(shù),并且會(huì)執(zhí)行該析構(gòu)函數(shù)的主體。
按照非靜態(tài)成員對(duì)象的析構(gòu)函數(shù)在類聲明中的顯示順序的相反順序調(diào)用這些函數(shù)。用于這些成員的構(gòu)造的可選成員優(yōu)化列表不影響構(gòu)造或析構(gòu)的順序。
非虛擬基類的析構(gòu)函數(shù)以聲明的相反順序被調(diào)用。
虛擬基類的析構(gòu)函數(shù)以聲明的相反順序被調(diào)用。

// order_of_destruction.cpp
#include <stdio.h>

struct A1   { virtual ~A1() { printf("A1 dtor\n"); } };
struct A2 : A1 { virtual ~A2() { printf("A2 dtor\n"); } };
struct A3 : A2 { virtual ~A3() { printf("A3 dtor\n"); } };

struct B1   { ~B1() { printf("B1 dtor\n"); } };
struct B2 : B1 { ~B2() { printf("B2 dtor\n"); } };
struct B3 : B2 { ~B3() { printf("B3 dtor\n"); } };

int main() {
  A1 * a = new A3;
  delete a;
  printf("\n");

  B1 * b = new B3;
  delete b;
  printf("\n");

  B3 * b2 = new B3;
  delete b2;
}

輸出:

A3 dtor
A2 dtor
A1 dtor

B1 dtor

B3 dtor
B2 dtor
B1 dtor

虛擬基類
按照與虛擬基類在定向非循環(huán)圖形中顯示的順序的相反順序調(diào)用這些虛擬基類的析構(gòu)函數(shù)(深度優(yōu)先、從左到右、后序遍歷)。下圖描述了繼承關(guān)系圖。

2016122142248275.jpeg (107×121)

演示虛擬基類的繼承關(guān)系圖
下面列出了圖中顯示的類的類頭。

  • class A
  • class B
  • class C : virtual public A, virtual public B
  • class D : virtual public A, virtual public B
  • class E : public C, public D, virtual public B

為了確定 E 類型的對(duì)象的虛擬基類的析構(gòu)順序,編譯器將通過(guò)應(yīng)用以下算法來(lái)生成列表:

  1. 向左遍歷關(guān)系圖,并從關(guān)系圖中的最深點(diǎn)開(kāi)始(在此示例中,為 E)。
  2. 執(zhí)行左移遍歷,直到訪問(wèn)了所有節(jié)點(diǎn)。記下當(dāng)前節(jié)點(diǎn)的名稱。
  3. 重新訪問(wèn)上一個(gè)節(jié)點(diǎn)(向下并向右)以查明要記住的節(jié)點(diǎn)是否為虛擬基類。
  4. 如果記住的節(jié)點(diǎn)是虛擬基類,請(qǐng)瀏覽列表以查看是否已將其輸入。如果它不是虛擬基類,則將其忽略。
  5. 如果記住的節(jié)點(diǎn)尚未包含在列表中,請(qǐng)將其添加到列表的底部。
  6. 向上遍歷關(guān)系圖并沿下一個(gè)路徑向右遍歷。
  7. 轉(zhuǎn)到步驟 2。
  8. 在用完最后一個(gè)向上路徑時(shí),請(qǐng)記下當(dāng)前節(jié)點(diǎn)的名稱。
  9. 轉(zhuǎn)到步驟 3。
  10. 繼續(xù)執(zhí)行此過(guò)程,直到底部節(jié)點(diǎn)再次成為當(dāng)前節(jié)點(diǎn)。

因此,對(duì)于 E 類,析構(gòu)順序?yàn)椋?/p>

  1. 非虛擬基類 E。
  2. 非虛擬基類 D。
  3. 非虛擬基類 C。
  4. 虛擬基類 B。
  5. 虛擬基類 A。

此過(guò)程將生成唯一項(xiàng)的有序列表。任何類名均不會(huì)出現(xiàn)兩次。在構(gòu)造列表后,將以相反的順序遍歷該列表,并且將調(diào)用列表中每個(gè)類(從最后一個(gè)到第一個(gè))的析構(gòu)函數(shù)。

如果某個(gè)類中的構(gòu)造函數(shù)或析構(gòu)函數(shù)依賴于要先創(chuàng)建或保留更長(zhǎng)時(shí)間的另一個(gè)組件(例如,如果 A 的析構(gòu)函數(shù)(上圖中所示)依賴于執(zhí)行其代碼時(shí)仍存在 B),則構(gòu)造或析構(gòu)的順序特別重要,反之亦然。
繼承關(guān)系圖中各個(gè)類之間的這種相互依賴項(xiàng)本質(zhì)上是危險(xiǎn)的,因?yàn)樯院笈缮惪梢愿淖钭筮叺穆窂?,從而更改?gòu)造和析構(gòu)的順序。
非虛擬基類
按照相反的順序(按此順序聲明基類名稱)調(diào)用非虛擬基類的析構(gòu)函數(shù)??紤]下列類聲明:

class MultInherit : public Base1, public Base2
...

在前面的示例中,先于 Base2 的析構(gòu)函數(shù)調(diào)用 Base1 的析構(gòu)函數(shù)。
顯式析構(gòu)函數(shù)調(diào)用
很少需要顯式調(diào)用析構(gòu)函數(shù)。但是,對(duì)置于絕對(duì)地址的對(duì)象進(jìn)行清理會(huì)很有用。這些對(duì)象通常使用采用位置參數(shù)的用戶定義的 new 運(yùn)算符進(jìn)行分配。 delete 運(yùn)算符不能釋放該內(nèi)存,因?yàn)樗皇菑淖杂纱鎯?chǔ)區(qū)分配的(有關(guān)詳細(xì)信息,請(qǐng)參閱 new 和 delete 運(yùn)算符)。但是,對(duì)析構(gòu)函數(shù)的調(diào)用可以執(zhí)行相應(yīng)的清理。若要顯式調(diào)用 s 類的對(duì)象 String 的析構(gòu)函數(shù),請(qǐng)使用下列語(yǔ)句之一:

s.String::~String();   // Nonvirtual call
ps->String::~String();  // Nonvirtual call

s.~String();    // Virtual call
ps->~String();   // Virtual call

可以使用對(duì)前面顯示的析構(gòu)函數(shù)的顯式調(diào)用的表示法,無(wú)論類型是否定義了析構(gòu)函數(shù)。這允許您進(jìn)行此類顯式調(diào)用,而無(wú)需了解是否為此類型定義了析構(gòu)函數(shù)。顯式調(diào)用析構(gòu)函數(shù),其中未定義的析構(gòu)函數(shù)無(wú)效。

相關(guān)文章

  • C語(yǔ)言解決字符串中插入和刪除某段字符串問(wèn)題

    C語(yǔ)言解決字符串中插入和刪除某段字符串問(wèn)題

    這篇文章主要介紹了C語(yǔ)言解決字符串中插入和刪除某段字符串問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 使用C++遞歸求解跳臺(tái)階問(wèn)題

    使用C++遞歸求解跳臺(tái)階問(wèn)題

    這篇文章主要介紹了使用C++求解跳臺(tái)階問(wèn)題的方法,通過(guò)遞歸算法來(lái)解決,不算難,文中給出了計(jì)算思路,需要的朋友可以參考下
    2016-02-02
  • Opencv 馬賽克和毛玻璃效果與圖片融合的實(shí)現(xiàn)

    Opencv 馬賽克和毛玻璃效果與圖片融合的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了通過(guò)OpenCV實(shí)現(xiàn)馬賽克和毛玻璃濾鏡效果與圖片的融合,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 6個(gè)變態(tài)的C語(yǔ)言Hello World程序

    6個(gè)變態(tài)的C語(yǔ)言Hello World程序

    這篇文章主要介紹了6個(gè)變態(tài)的C語(yǔ)言Hello World程序,需要的朋友可以參考下
    2016-05-05
  • C++中的六個(gè)函數(shù)

    C++中的六個(gè)函數(shù)

    本文給大家介紹了C++中的六個(gè)函數(shù),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-05-05
  • C語(yǔ)言撲克牌游戲示例

    C語(yǔ)言撲克牌游戲示例

    大家好,本篇文章主要講的是C語(yǔ)言撲克牌游戲示例,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 從頭學(xué)習(xí)C語(yǔ)言之二維數(shù)組

    從頭學(xué)習(xí)C語(yǔ)言之二維數(shù)組

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言之二維數(shù)組,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • Qt+OpenCV利用幀差法實(shí)現(xiàn)車輛識(shí)別

    Qt+OpenCV利用幀差法實(shí)現(xiàn)車輛識(shí)別

    所謂幀差法也就是對(duì)連續(xù)圖像幀做差分運(yùn)算,其結(jié)果與定義好的閾值比較,若大于閾值則為運(yùn)動(dòng)目標(biāo)值為1,否則值為0?。本文將利用幀差法實(shí)現(xiàn)車輛識(shí)別,感興趣的可以了解一下
    2022-08-08
  • C語(yǔ)言詳細(xì)分析講解多文件的程序設(shè)計(jì)

    C語(yǔ)言詳細(xì)分析講解多文件的程序設(shè)計(jì)

    所謂的C語(yǔ)言多文件編程就是,將代碼實(shí)現(xiàn)模塊化。比如說(shuō)一個(gè)項(xiàng)目的一項(xiàng)功能放在一個(gè)一個(gè)文件里,然后將實(shí)現(xiàn)這個(gè)功能的函數(shù)放在一個(gè)c文件<BR>
    2022-04-04
  • C++?Boost?Spirit進(jìn)階教程

    C++?Boost?Spirit進(jìn)階教程

    Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開(kāi)發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱
    2022-11-11

最新評(píng)論