本页使用了标题或全文手工转换

三法則 (C++程式設計)

维基百科,自由的百科全书
跳转至: 导航搜索

三法則英语rule of threethe Law of The Big ThreeThe Big Three三法則三大定律)在 C++ 程式設計裡,它是一個以設計的基本原則而制定的定律,三法則的要求在於,假如類別有明顯地定義下列其中一個成員函式,那麼程式設計師必須連其他二個成員函式也一同編寫至類別內,亦即下列三個成員函式缺一不可。 [1]:

上述三個函式是特別的成員函式,假如程式設計師沒有自行定義或是編寫宣告它們,那麼編譯器會自動地建立它們,並且會編譯至應用程式內。相反地,假如程式設計師有定義上述三者其中一個函式,那麼由編譯器自動產生出來的上述三個函式是不會搭配到這個類別內。三法則(Rule of three)這個專有名詞是由 Marshall Cline 於 1991 年創立的[2]

這個法則的修正版本是,假如類別有用到 RAII(資源的取得就是初始化,Resource Acquisition Is Initialization),則可以不必定義解構子(也就是所謂的二大定律,The Law of The Big Two[3])。

因為隐式生成(英语implicitly-generated;由編譯器自動產生)的建構子與設定運算子可以很容易地複製類別內所有的資料成員[4],當資料成員是指標型態時,指標位址會隨著類別而跟著被複製,要注意的是,直接地複製指標位址是一項非常危險的動作,所以只要類別有封裝指標型態的資料結構,或是類別有封裝外部參照的資料成員(例如:指標型態的資料成員),程式設計師應該為此定義显式(英语explicit;由程式設計師來編寫清楚明確的)的複製建構子,以及複製設定運算子

从C++11开始,三法则扩充为五法则:

原始碼範例[编辑]

C/C++[编辑]

C/C++ 原始碼範例
class_a.h 主函式
#ifndef _CLASS_A_H_
#define _CLASS_A_H_
 
#ifndef _MSC_VER
#undef NULL
#define NULL 0
#endif
#include <iostream>
#include <cstdlib>
#define BUFFER_SIZE 7
 
using namespace std;
 
class ClassA
{
public:
    // 三種建構子
    ClassA()
    {
        cout<<"ClassA():"<<endl;
        this->setAlloc(BUFFER_SIZE);
        this->setData();
    }
    ClassA(const int n)
    {
        cout<<"ClassA(const int n):"<<endl;
        this->setAlloc(n);
        this->setData();
    }
    // 複製建構子
    ClassA(const ClassA& clone)
    {
        cout<<"ClassA(const ClassA& clone):"<<endl;
        this->setAlloc(clone.m_N);
        this->setData(clone.m_pn);
    }
    // 複製指定運算子成員函式
    ClassA& operator=(const ClassA& clone)
    {
        cout<<"ClassA& operator=(const ClassA& clone)"<<endl;
        // 保護:禁止自己設值給自己
        if ( this != &clone )
        {
            this->setData(clone.m_pn);
        }
        return *this;
    }
    // 解構子
    ~ClassA()
    {
        cout<<"~Destructor!!!"<<endl;
        // 釋放記憶體
        delete [] this->m_pn;
    }
    // 配置
    void setAlloc(const int n)
    {
        this->m_N = n;
        // 配置一塊記憶體給指標
        this->m_pn = new int[this->m_N];
    }
    // 填入一堆的整數值
    void setData(int* pn = NULL)
    {
        for ( int i = 0; i < this->m_N; i ++)
        {
            // 給初始值
            if ( pn == NULL )
            {
                this->m_pn[i] = (2 * i + 1);
            }
            // 複製指標儲存的整數值
            else
            {
                this->m_pn[i] = pn[i];
            }
        }
    }
    // 列印顯示
    void print(void)
    {
        for ( int i = 0; i < this->m_N; i ++)
        {
            cout<<" "<<this->m_pn[i];
        }
        cout<<endl;
    }
private:
    // 指標
    int* m_pn;
    // 元素個數
    int m_N;
};
 
#endif
// Headers and Macros
#ifndef _MSC_VER
#undef NULL
#define NULL 0
#endif
#include <iostream>
#include <cstdlib>
#include "class_a.h"
using namespace std;
//
//Main Function
#ifndef _MSC_VER
int
#else
void
#endif
main(int argc, char** argv)
{
    // 區塊
    {
        // 建立第一個物件
        ClassA A(BUFFER_SIZE);
        cout<<" A =>";
        A.print();
        {
            // 開始執行 ClassA(const ClassA& clone)
            ClassA B = A;
            cout<<" B =>";
            B.print();
        }
        {
            ClassA C;
            // 開始執行 ClassA& operator=(const ClassA& clone)
            C = A;
            cout<<" C =>";
            C.print();
        }
    }
    system("PAUSE");
    return
#ifndef _MSC_VER
        EXIT_SUCCESS
#endif
        ;
}

參考資料[编辑]

  1. ^ Stroustrup, Bjarne. The C++ Programming Language 3. Addison-Wesley. 2000: 283–4. ISBN 978-0201700732. 
  2. ^ Koenig, Andrew; Barbara E. Moo. C++ Made Easier: The Rule of Three. Dr. Dobb's Journal. 2001-06-01 [2009-09-08]. 
  3. ^ Karlsson, Bjorn; Wilson, Matthew. The Law of the Big Two. The C++ Source. Artima. 2004-10-01 [2008-01-22]. 
  4. ^ 比雅尼·史特勞斯特魯普. The C++ Programming Language. : 第 271 頁.