1. 程式人生 > >Part4 類與對象 4.3構造函數

Part4 類與對象 4.3構造函數

c++11 con rt4 類與對象 include pre 指示 被調用 c++98

構造函數的作用:在對象被創建時使用特定的值構造對象,將對象初始化為一個特定的初始狀態。
構造函數的形式:
  函數名與類名相同;
  不能定義返回值類型,也不能有return語句;
  可以是內聯函數。

默認構造函數:調用時可以不需要實參的構造函數
  1 參數表為空的構造函數
  2 全部參數都有默認值的構造函數
下面兩個都是默認構造函數,如在類中同時出現,將產生編譯錯誤:

Clock();
Clock(int newH=0,int newM=0,int newS=0);

隱含生成的構造函數:如果程序中未定義構造函數,編譯器將在需要時自動生成一個默認構造函數
  參數列表為空,不為數據成員設置初始值;
  如果類內定義了成員的初始值,則使用內類定義的初始值;
  如果沒有定義類內的初始值,則以默認方式初始化;
  基本類型的數據默認初始化的值是不確定的。

如果程序中已定義構造函數,默認情況下編譯器就不再隱含生成默認構造函數。
如果此時依然希望編譯器隱含生成默認構造函數,可以使用“=default”。

class Clock {
public:
   Clock() = default; //指示編譯器提供默認構造函數
   Clock(int newH, int newM, int newS);     //構造函數
private:
   int hour, minute, second;
};
//4-2 4-1修改版
#include<iostream>
using namespace std;
class Clock{
public
: Clock(int newH, int newM, int newS);//加入構造函數 void setTime(int newH = 0, int newM = 0, int newS = 0); void showTime(); private: int hour, minute, second; }; //構造函數的實現 Clock::Clock(int newH, int newM, int newS):hour(newH),minute(newM),second(newS){}//參數括號後大括號之前是初始化列表,比在函數體中寫賦值表達式效率高 void Clock::setTime(int
newH, int newM, int newS){ hour = newH; minute = newM; second = newS; } void Clock::showTime(){ cout << hour << ":" << minute << ":" << second; } //對象的使用 int main(){ Clock c(0,0,0); c.showTime(); return 0; }
//4-3 加入默認構造函數
#include<iostream>
using namespace std;
class Clock{
public:
    Clock(int newH, int newM, int newS);//加入構造函數
    Clock(); //默認構造函數
    void setTime(int newH = 0, int newM = 0, int newS = 0);
    void showTime();
private:
    int hour, minute, second;
};
Clock::Clock(): hour(0),minute(0),second(0) { }//默認構造函數,初始化列表中用自己約定的值,沒有參數傳進來
Clock::Clock(int newH, int newM, int newS):hour(newH),minute(newM),second(newS){}//參數括號後大括號之前是初始化列表,比在函數體中寫賦值表達式效率高
void Clock::setTime(int newH, int newM, int newS){
    hour = newH;
    minute = newM;
    second = newS;
}
void Clock::showTime(){
    cout << hour << ":" << minute << ":" << second;
}
//對象的使用
int main(){
    Clock c1(1,1,1);
    Clock c2;
    c1.showTime();
    c2.showTime();
    return 0;
}

委托構造函數:類中往往有多個構造函數,只是參數表和初始化列表不同,其初始化算法都是相同的,這時,為了避免代碼重復,可以使用委托構造函數。
之前Clock類的兩個構造函數:

Clock(int newH, int newM, int newS) : hour(newH),minute(newM),  second(newS)  { }        //構造函數
Clock::Clock(): hour(0),minute(0),second(0) { }//默認構造函數

委托構造函數使用類的其他構造函數執行初始化過程:

Clock(int newH, int newM, int newS):  hour(newH),minute(newM),  second(newS){}
Clock(): Clock(0, 0, 0) { }//無參的構造函數直接調用有參的構造函數

復制構造函數:是一種特殊的構造函數,其形參為本類的對象引用。作用是用一個已存在的對象去初始化同類型的新對象。

class 類名 {
public:
    類名(形參);//構造函數
    類名(const  類名 &對象名);//復制構造函數,常引用,只能讀,不能改傳進來的那個對象的數據
    //       ...
};
類名::類(const  類名 &對象名)//復制構造函數的實現
{    函數體    }

復制構造函數被調用的三種情況:
  1 定義一個對象時,以本類另一個對象作為初始值,發生復制構造;
  2 如果函數的形參是類的對象,調用函數時,將使用實參對象初始化形參對象,發生復制構造;
  3 如果函數的返回值是類的對象,函數執行完成返回主調函數時,將使用return語句中的對象初始化一個臨時無名對象,傳遞給主調函數,此時發生復制構造。

隱含的復制構造函數:如果沒有為類聲明拷貝初始化構造函數,則編譯器自己生成一個隱含的復制構造函數。
這個構造函數執行的功能是:用作為初始值的對象的每個數據成員的值,初始化將要建立的對象的對應數據成員。

如果不希望對象被復制構造:
  1 C++98 做法:將復制構造函數聲明為private,並且不提供函數的實現。
  2 C++11 做法:用“=delete”指示編譯器不生成默認復制構造函數。

class Point {   //Point 類的定義
public:
    Point(int xx=0, int yy=0) { x = xx; y = yy; }    //構造函數,內聯
    Point(const Point& p) = delete;  //指示編譯器不生成默認復制構造函數
private:
    int x, y; //私有數據
};

int main(){
    Point a;
    Point b(a); //情況一:用a初始化b,調用復制構造函數
    cout << b.getX() << endl;
    fun1(b);    //情況二:對象b作為fun1的實參,調用復制構造函數
    b = fun2(); //情況三:函數返回值是類對象,函數返回時,調用復制構造函數
    cout << b.getX() << endl;
    return 0;
}

Part4 類與對象 4.3構造函數