C++面向對象-5-類的構造函數調用規則

繼續來學習構造函數的知識,通過前面學習,我們知道一個類中可以有 無參構造,有參構造,拷貝構造,那麼編譯器是如何決定調用這些構造函數,本篇就來學習這個調用規則。

知識點:

默認情況下,C++編譯器至少給一個類添加3個函數
1.默認構造函數(無參,函數體爲空)
2.默認析構函數(無參,函數體爲空)
3.默認拷貝構造函數,對屬性進行值拷貝

構造函數的調用規則如下:
如果用戶定義有參構造函數,c++不再提供默認無參構造,但是會提供默認拷貝構造
如果用戶定義拷貝構造函數,c++不會再提供其他構造函數

下面我們分別用代碼來驗證以上知識點。

 

1.只要創建一個類,C++編譯器會給這個類至少添加三個函數。

這裏,我們知道編譯器會自動添加無參構造函數,所以我們來代碼證明看看編譯器添加拷貝構造的效果。

#include<iostream>
using namespace std;

class Point
{

public:

    //構造函數
    Point()
    {
        cout << "調用了構造函數"<< endl;
    }

    //有參構造
    Point(int x, int y)
    {
	cout << "調用了有參構造函數" << endl;
	X = x;
	Y = y;
    }

    //拷貝構造
    Point(const Point &p)
    {
	cout << "調用了拷貝構造函數" << endl;
	//將p的屬性拷貝到當前類的初始化
	X = p.X;
	Y = p.Y;
    }

    //析構函數
    ~Point()
    {
        cout << "調用了析構函數" << endl;
    }

public:
    int X;
    int Y;
};

void test01()
{
    Point p;
    p.X = 5;
    p.Y = 5;
    //利用拷貝構造
    Point p1(p);
    cout << "p1的X值爲" << p1.X << endl;
}

int main()
{
    test01();
    system("pause");
    return 0;
}

上面代碼我們補全了無參和有參和拷貝構造,運行代碼

這個結果是我們前面一篇就已經知道的效果,現在我們把上面代碼中的拷貝構造函數給註銷,看看編譯器會不會給我們自動加上拷貝構造函數。

註銷這段代碼,然後test01()代碼保持不變,運行

分析:

1)Point p肯定走默認無參構造,然後p對象進行了X和Y的設置值

2)通過右側運行結果,顯示p1的X座標也是5,說明發生了拷貝,而且有兩個析構函數調用的打印

3)第二點說明了,C++編譯器自動給我們運行了拷貝構造,至於這個拷貝代碼是什麼,我們不清楚,但是效果就是,X和Y都進行值的拷貝。

 

2.證明如果用戶提供有參構造,編譯器不再提供無參構造

我們把上面類代碼改成這樣,不寫無參構造,只留下一個有參構造,然後代碼中特意調用無參構造,看看報什麼錯誤。

#include<iostream>
using namespace std;

class Point
{

public:

    //有參構造
    Point(int x, int y)
    {
	cout << "調用了有參構造函數" << endl;
	X = x;
	Y = y;
    }

    
    //析構函數
    ~Point()
    {
        cout << "調用了析構函數" << endl;
    }

public:
    int X;
    int Y;
};

void test01()
{
    Point p;
}

int main()
{
    test01();
    system("pause");
    return 0;
}

嘗試運行以上代碼

這裏代碼想調用無參構造,但是由於這個規則(用戶寫了有參構造,編譯器不會自動添加無參構造),所以報以上錯誤。這裏雖然不提供無參構造,但是還是會提供拷貝構造,下面代碼改成這樣,運行可以證明

 

3.證明如果用戶寫了拷貝構造,編譯器不提供其他構造函數

#include<iostream>
using namespace std;

class Point
{

public:

    //拷貝構造
    Point(const Point &p)
    {
	cout << "調用了拷貝構造函數" << endl;
	//將p的屬性拷貝到當前類的初始化
	X = p.X;
	Y = p.Y;
    }

    
public:
    int X;
    int Y;
};

void test01()
{
    Point p;
}

int main()
{
    test01();
    system("pause");
    return 0;
}

只有一個拷貝構造,編譯一下,

這個證明了如果用戶提供拷貝構造函數,編譯器不會提供無參構造函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章