簡介
三法則這個專有名詞是由馬歇爾·克來恩於1991年創立的,假設類有用到RAII,可以不必定義
析構函式。 因為隱式生成的構造函式與賦值運算符可以很容易地複製類內所有的數據成員,當數據成員是指針類型時,指針地址會隨著類而跟著被複製。要注意的是,直接地複製指針地址是一項非常危險的動作,所以只要類有封裝指針類型的數據結構,或是類有封裝外部引用的數據成員,例如指針類型的數據成員,程式設計師應該為此而定義顯式的複製構造函式與賦值運算符。AII全稱為Resource Acquisition Is Initialization,它是在一些面向對象語言中的一種慣用法。RAII源於C++,在Java,C#,D,Ada,Vala和Rust中也有套用。1984-1989年期間,比雅尼·史特勞斯特魯普和安德魯·柯尼希在設計C++異常時,為解決資源管理時的異常安全性而使用了該用法,後來比雅尼·史特勞斯特魯普將其稱為RAII。RAII要求,資源的有效期與持有資源的對象的生命期嚴格綁定,即由對象的構造函式完成資源的分配(獲取),同時由析構函式完成資源的釋放。在這種要求下,只要對象能正確地析構,就不會出現資源泄露問題。
組成
析構函式
析構函式(Destructordtor)在面向對象程式設計里是一個方法,當對象的生命周期結束時,它會自動地被調用運行。它最主要的目的在於,清空並釋放對象先前創建或是占用的存儲器資源。析構函式的整體使用概念關鍵在於RAII。一個具備垃圾回收機制的程式語言,無法確保析構函式是否會被運行,通常這類的程式語言不屬於RAII的範圍內。這類的程式語言,只要經由某個適當的函式,通常會調用Dispose()函式,做調用的動作,那么它一定會從現有資源釋放對象。與使用垃圾回收機制的Finalize()相比,建議使用析構函式是釋放資源的適當做法。
複製構造函式
複製構造函式(Copy constructor)是C++程式語言中的一種特別的構造函式,習慣上用來創建一個全新的對象,這個全新的對象相當於已存在對象的副本。這個構造函式只有一個參數(引數):就是用來賦值對象的引用(常用const修飾)。構造函式也可以有更多的參數,但除了最左第一個參數是該類的引用類型外,其它參數必須有默認值。
類的賦值構造函式原型通常如下:Class_name(const Class_name & src);
一般來說,假如程式設計師沒有自行編寫賦值構造函式,那么編譯器會自動地替每一個類創建一個賦值構造函式;相反地,程式設計師有自行編寫賦值構造函式,那么編譯器就不會創建它。當對象包括指針或是不可分享的引用時,程式設計師編寫顯式的賦值構造函式是有其必要性的,例如處理檔案的部分,除了賦值構造函式之外,應該還要再編寫析構函式與賦值運算符的部分,也就是三法則。
賦值運算符
在C++程式語言里,賦值運算符(assignment operator)是用等號 = 符號。就像其他的C++運算符一樣,它可以作為重載。賦值賦值運算符是一個特別的賦值運算符,通常是用來把已存在的對象指定給其他相同類別的對象。它是一個特別的成員函式,如果程式設計師沒有定義這個成員函式,那么編譯器會自動地產生這個成員函式。編譯器產生的代碼是以單一成員進行對象賦值的動作。賦值賦值運算符,這個成員函式與賦值構造函式的相異點在於,它一定會清除目標對象的數據成員(以及確實掌控自我設值的動作),而賦值構造函式不會初始化類別的數據成員。
代碼示例
#ifndef _HEADER_H_ #define _HEADER_H_ // //判斷是否為微軟編譯器#ifndef _MSC_VER #undef NULL #define NULL 0 #endif // #include <iostream> #include <limits> // using std :: cin ; using std :: cout ; using std :: endl ; // //類別:方塊class CCube { public : //建構子 CCube (); //含有參數的建構子 CCube ( double length , double width , double height ); //三法則:解構子 ~ CCube (); //三法則:複製建構子 CCube ( const CCube & sample ); //三法則:設定運運算元 CCube & operator = ( const CCube & sample ); //設定長寬高 void setLength ( double length ); void setWidth ( double width ); void setHeight ( double height ); //取得長寬高 double getLength () const ; double getWidth () const ; double getHeight () const ; //計算體積 double getVolume () const ; protected : private : //長寬高 double m_Length ; double m_Width ; double m_Height ; }; // void PAUSE ( void ); // #endif