1. 程式人生 > >C++---對象的構造

C++---對象的構造

c++編譯 變量 test name 初始化 sin 顯示調用 成員 ima

一.對象的構造(上)

Q:對象中成員變量的初始值是多少?

#include <iostream>

using namespace std;

class Test
{
    private:
        int i;
        int j;
    public:
        int getI()
        {
            return i;
        }
        int getJ()
        {
            return j;
        }
};

int main()
{
    Test t1;

    cout<<"t1.getI()="<<t1.getI()<<endl;
    cout<<"t1.getJ()="<<t1.getJ()<<endl;
}

輸出的結果為
技術分享圖片

#include <iostream>

using namespace std;

class Test
{
    private:
        int i;
        int j;
    public:
        int getI()
        {
            return i;
        }
        int getJ()
        {
            return j;
        }
};

Test gt;

int main()
{
    cout<<"gt.getI()="<<gt.getI()<<endl;
    cout<<"gt.getJ()="<<gt.getJ()<<endl;

    Test t1;

    cout<<"t1.getI()="<<t1.getI()<<endl;
    cout<<"t1.getJ()="<<t1.getJ()<<endl;

    Test* pt = new Test;

    cout<<"pt->getI()="<<pt->getI()<<endl;
    cout<<"pt->getJ()="<<pt->getJ()<<endl;

    delete pt;

    return 0;

}

結果如圖
技術分享圖片
小結
從程序設計的角度,對象只是變量
1.在棧上創建對象時,成員變量初始為隨機值
2.在堆上創建對象時,成員變量初始值為隨機值
3.在靜態區創建對象時,成員變量初始值為0值

解決方案:
1.在類中提供一個public的intialize函數
2.對象創建後立即調用intialize函數進行初始化
示例

#include <iostream>

using namespace std;

class Test
{
    private:
        int i;
        int j;
    public:
        int getI()
        {
            return i;
        }
        int getJ()
        {
            return j;
        }
        void initialize()
        {
            i = 1;
            j = 2;
        } 
};

Test gt;

int main()
{
    gt.initialize();
    cout<<"gt.getI()="<<gt.getI()<<endl;
    cout<<"gt.getJ()="<<gt.getJ()<<endl;

    Test t1;
    //t1.initialize();
    cout<<"t1.getI()="<<t1.getI()<<endl;
    cout<<"t1.getJ()="<<t1.getJ()<<endl;
    t1.initialize();

    Test* pt = new Test;
    pt->initialize();
    cout<<"pt->getI()="<<pt->getI()<<endl;
    cout<<"pt->getJ()="<<pt->getJ()<<endl;

    delete pt;

    return 0;

}

運行結果
技術分享圖片
Q:當intialize的位置出現了改變的話,還會對其進行初始化嗎
技術分享圖片技術分享圖片
輸出結果如圖所示,發現intialize位置改變了之後,初始化也出現了問題
存在的問題
1.intialize只是一個普通函數,必須顯示調用
2.如果為調用intialize函數,運行結果是不確定的
解決方法
C++中可以定義與類名相同的特殊成員函數--這種特殊的成員函數叫做構造函數
1.構造函數沒有任何返回類型的聲明
2.構造函數在對象定義時自動被調用

示例

#include <iostream>

using namespace std;

class Test
{
    private:
        int i;
        int j;
    public:
        int getI()
        {
            return i;
        }
        int getJ()
        {
            return j;
        }
        Test()
        {
            printf("Test() Begin\n");

            i = 1;
            j = 2;

            printf("Test() End\n");
        }
};

Test gt;

int main()
{

    cout<<"gt.getI()="<<gt.getI()<<endl;
    cout<<"gt.getJ()="<<gt.getJ()<<endl;

    Test t1;

    cout<<"t1.getI()="<<t1.getI()<<endl;
    cout<<"t1.getJ()="<<t1.getJ()<<endl;
    t1.initialize();

    Test* pt = new Test;

    cout<<"pt->getI()="<<pt->getI()<<endl;
    cout<<"pt->getJ()="<<pt->getJ()<<endl;

    delete pt;

    return 0;

}

運行結果
技術分享圖片
小結
1.每個對象在使用之前都應該初始化
2.類的構造函數用於對象的初始化
3.構造函數與類同名並且沒有返回值
4.構造函數在對象定義時自動被調用

二.對象的構造(中)

帶有參數的構造函數
1.構造函數可以根據需要定義參數
2.一個類中可以存在多個重載的構造函數
3.構造函數的重載遵循C++重載的規則
對象定義和對象聲明不同
1.對象定義--申請對象的空間並調用構造函數
2.對象聲明--告訴編譯器存在這樣一個對象
示例

#include <iostream>
using namespace std;

class Test
{
public:
    Test() 
    { 
        cout<<"Test()"<<endl;;
    }
    Test(int v) 
    { 
        cout<<"Test(int v)="<<v<<endl;
    }
};

int main()
{
    Test t;      // 調用 Test()
    Test t1(1);  // 調用 Test(int v)
    Test t2 = 2; // 調用 Test(int v)

    int i(100);

    cout<<"i="<<i<<endl;

    return 0;
}

結果
技術分享圖片
小結
1.構造函數可以根據需要定義參數
2.構造函數之間可以存在重載關系
3.構造函數遵循C++中重載函數的規則
4.對象定義時會觸發構造函數的調用
5.在一些情況下可以手動調用構造函數

三.特殊的構造函數

1.無參構造函數--沒有參數的構造函數,當類中沒有定義構造函數時,編譯器默認提供一個無參構造函數,並且其函數體為空
2.拷貝構造函數--參數為const class_name&的構造函數,當類中沒有定義拷貝構造函數時,編譯器默認提供一個拷貝構造函數,簡單的進行成員變量的值的復制

拷貝構造函數的意義
1.兼容C語言的初始化方式
2.初始化行為能夠符合預期的邏輯
3.淺拷貝--拷貝後的物理狀態相同
4.深拷貝--拷貝後的邏輯狀態相同
小結
1.C++編譯器會默認提供構造函數
2.無參構造函數用於定義對象的默認初始狀態‘
3.拷貝構造函數在創建對象時拷貝對象的狀態
4.對象的拷貝由淺拷貝和深拷貝兩種方式

C++---對象的構造