構造函數和析構函數

構造函數和析構函數

15. 類和對象的關系。

它們之間的區別就像是整型和整型變量之間的區別一樣。我們可以定義多個整型變量,例如 int a,b,c;,并且可以為整型變量賦值。但是不能夠為整型賦值。類和對象也是一樣的。對象是類的實例化,我們可以為對象賦值,但是不能為類賦值。類只是告訴編譯器,在定義對象時如何在內存中為對象分配空間。

16. 構造函數和析構函數的調用。

在 C++中,不能通過構造函數或析構函數名稱來直接構建或釋放對象。當定義一個對象時會自動調用構造函數。例如:

CBook book; //在棧中構建對象
CBook *pBook = new CBook(); //在堆中構建對象

上述兩行代碼都會調用構造函數。對于析構函數來說,當對象是在棧中構建時,作用域消失會自動調用析構函數。而在堆中構建對象時,當調用 delete 運算符釋放對象會導致析構函數被調用。

總之,構造函數在創建類對象的時候被自動調用,析構函數在使用 delete 運算符或類對象生命期結束時,由系統自動調用。

17. 代碼膨脹

下面的代碼有哪些不足之處?

class CBook //定義一個 CBook 類
{
public:
    double m_Price; //定義數據成員
    char *m_BookName;
    char *m_Press;
    CBook() //默認構造函數
    {
        m_BookName = new char[128];
        m_Press = new char[128];
        memset(m_BookName, 0, 128);
        memset(m_Press, 0, 128);
        strcpy(m_BookName, "Visual C++");
        strcpy(m_Press, "電子工業");
        m_Price = 0.0;
    }
    ~CBook() //析構函數
    {
        //...
        delete [] m_BookName;
        delete [] m_Press;
    }
};
int main(int argc, char* argv[])
{
    CBook book; //定義一個 CBook 類對象 book
    int state = 0; //定義一個整型變量
    switch(state)
    {
        case 0: //分支判斷
        {
            printf("%s\n",book.m_BookName); //輸出信息
            return 0; //函數結束
        }
        case 1: //分支判斷
        {
             printf("%f\n",book.m_Price); //輸出信息
            return 0; //函數結束
        }
        default: //默認情況
            return 0; //函數結束
    }
    return 0;
}

由于 CBook 類的析構函數是內聯成員函數,因此上述代碼在每一個 return 語句之前,析構函數均會被展開。因為 return 語句表示當前函數調用結束,book 對象的生命期也就結束了,自然調用其析構函數。根據上述分析,main 函數中 switch 語句的編寫是非常不明智的,下面對其進行修改,將 return 語句替換為 break 語句。

int main(int argc, char* argv[])
{
    CBook book; //定義一個 CBook 類對象 book
    int state = 0; //定義一個整型變量
    switch(state)
    {
        case 0: //分支判斷
        {
            printf("%s\n",book.m_BookName); //輸出信息
            break; //函數結束
        }
        case 1: //分支判斷
        {
            printf("%f\n",book.m_Price); //輸出信息
            break; //函數結束
        }
        default: //默認情況
            break; //函數結束
    }
    return 0;
}

18. 轉換函數

請完成下面代碼實現 main 函數中的類型轉換(不能使用運算符重載)。

class CPerson
{
public:
    int m_nAge;
    CPerson()
    {
        m_nAge = 0;
    }
};
int main(int argc, char* argv[])
{
    CPerson person = 10; //將該語句合法化
    return 0;
}

構造函數有一個特殊的功能,就是實現類型轉換。但是要求構造函數必須只能有一個參數。當該類型的參數賦值給類對象時,將實現類型轉換。這樣的構造函數也被稱為轉換函數。

通過構造函數來實現類型轉換。修改 CPerson 類的構造函數,使其包含
一個整數作為參數。例如:

CPerson(intAge)
{
    m_nAge = Age;
}

這樣,main 函數中的“CPerson person = 10;”語句就合法了。

19. C++ 中的 explicit 關鍵字有何作用?

explicit 關鍵字的作用是禁止將構造函數作為轉換函數。例如,如果一個類的構造函數中只包含一個整型參數,在構造函數前使用 explicit 關鍵字可以阻止像 CPerson person = 10;這樣的語句執行,導致編譯錯誤。

20. 調用構造函數

以下代碼中輸出結果是 0 嗎,為什么?

struct A
{
    int m_i;
    A( int i )
        : m_i(i)
    {
        //...
    }
    A()
    {
        A(0);
    }
};
int main(int argc, char* argv[])
{
    A object;
    cout << object.m_i << endl;
    return 0;
}

在 C++中,如果確定了某一個構造函數創建對象,在構造函數中如果調用其他重載的構造函數,它再不會執行其他構造函數的初始化部分代碼,而是執行函數體部分的代碼。

不會是 0 。因為在默認構造函數中調用一個內部的帶參數的構造函數是用戶的行為,而不是編譯器的行為,就像是調用普通的函數一樣,它不會執行構造函數的初始化部分。因此輸出結果不會是 0 。

參考資料:
C++ explicit關鍵字詳解

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 構造函數簡介 在上一個章節我們在創建好類的對象之后,首先對它的每一個成員屬性賦值之后再對它們進行輸出操作,如果不賦...
    隨波逐流007閱讀 673評論 0 1
  • 我們之前使用的初始化方法大多如下面的形式: 接我們之前創建的Stock類。如果我們使用下面的方式初始化Stock類...
    ZYiDa閱讀 341評論 0 0
  • 今天為各位老師推薦的好書是《印光大師家庭教育嘉言錄》 印光大師非常重視家庭教育和因果教育。現代人內有煩惱習氣,外有...
    百行孝為先閱讀 460評論 0 0
  • 我在離你倆最近的世界邊緣, 卻遠去于未知的年華。 看你是花非花,是黑的媚,也是虛假; 又看你是短發齊耳,是裙角飄灑...
    橫豎都是死的說話不著調閱讀 213評論 0 0
  • 監控的第一天,很多人不敢遲到了,因為沒辦法代打卡。 可是,發又說沒車,先打卡。 我說有監控哦! 有什么事我擔著。何...
    流浪癡人閱讀 227評論 0 0