1. 程式人生 > >類和物件03 初始化列表 常物件 static

類和物件03 初始化列表 常物件 static

初始化列表 常物件 static

一.初始化列表

建構函式的初始化列表 ‘:’來指明成員的初始化方式

建構函式內部都是賦值

CLink(): a(20)     //(int a = 20 初始化a)

{

     b = 30;        //賦值

}

筆試題:以下這段程式碼  初始化列表中的執行順序問題

(1)Test (int a,int b):ma(a),mb(ma)

{

}

void Show ()

{

     cout<<ma<<ma<<endl;

     cout<<mb<mb<<endl;

}

Private:

    int ma;

    int mb;

int main()

{

   Test test1(10,20);

   test1.Show();

}

此時列印結果為:ma=10 ;mb=10;

ma先宣告 於是把a=10傳給ma ma在傳給mb

 

(2)Test (int a,int b):mb(ma),ma(a)

{

}

void Show ()

{

     cout<<ma<<ma<<endl;

     cout<<mb<mb<<endl;

}

Private:

   int ma;

   int mb;

   int main()

{

   Test test1(10,20);

   test1.Show();

}

此時列印結果仍為:ma=10 ;mb=10;

ma先宣告 於是把a=10傳給ma ma在傳給mb 與初始化列表順序無關

 

(3)Test (int a,int b):ma(a),mb(ma)

{

}

void show ()

{

     cout<<ma<<ma<<endl;

     cout<<mb<mb<<endl;

}

Private:

   int mb;

   int ma;

int main()

{

   Test test1(10,20);

   test1.show();

}

而此時列印的結果為:ma=10 ;mb=87487400(無效值);

此時mb先宣告 於是先把ma賦給mb 此時ma為無效值 所以mb也為無效值;

ma後宣告 於是把a = 10 傳給ma

為什麼兩次列印結果不同?

因為初始化列表中的執行順序只和成員宣告的順序有關 與初始化列表順序無關

(ma先宣告則在初始化列表中則ma先執行 mb後執行)

 

二.給出以下程式碼:const修飾的成員變數初始化問題

Test(int a,int b)

{

   ma = a;

   mb = b;

}

private:

      int ma;

      const int mb;

此時程式碼錯誤 相當於做了這樣的操作:

const int mb;(const修飾的mb必須要初始化)

mb = b;(常量不能修改)

我們知道函式內部是賦值操作

 

因此我們需要這樣做:

Test(int a,int b):mb(b)

{

   ma = a;

}

private:

      int ma;

      const int mb;

此時程式碼正確 相當於做了這樣的操作:

const int mb = b;

因此 const修飾的成員變數一定要在初始化列表中初始化

 

三.給出以下程式碼:常物件只能呼叫常方法問題 const修飾成員方法

void Show() const  //常方法

{

    count<<ma:<<ma<<endl;

   count<<mb:<<mb<<endl;

    Show(ma) //常方法呼叫普通方法

    (*this).Show(ma)//常方法中的this指標指向的是常物件 而常物件不能呼叫普通方法 所以常方法不能呼叫普通方法

}

 

void Show(int ma)  //普通方法

{

    count<<ma:<<ma<<endl;

    count<<mb:<<mb<<endl;

}

 

int main()

{

    const Test test1;//此時被const修飾的物件test1物件稱為常物件

    test1.Show()//常物件能呼叫普通方法嗎?

}

 

常方法與普通方法可以共存 因為引數不同

this指標的型別:類型別*const

這裡的this指標就為Tset*const

 

常物件只能呼叫常方法

常方法不能呼叫普通方法(常方法裡this指標指向的是常物件 常物件只能呼叫常方法)

普通物件可以呼叫常方法

普通方法可以呼叫常方法(普通方法裡this指標指向的是普通物件 普通物件可以呼叫常方法)

 

四.給出以下程式碼:引用的成員變數必須要在初始化列表中進行初始化

Test(int a,int b):ma(a)

{

mb = b;

}

private:

      int &ma;

      int mb;

 

 

五.static關鍵字:既能修飾變數 也能修飾方法 還能修飾成員變數

static修飾成員變數:

我們知道 普通成員變數是物件獨享的

然而static修飾的成員變數(靜態成員變數)不屬於物件私有 而是共享的 屬於類作用域

成員變數 ==> 不屬於物件 屬於類作用域

class Test

{

public:

 static int ma;//此時static修飾的ma就不屬於物件了

 int mb;

};

int Test::ma = 10;

注意:static修飾的成員變數一定要在類外初始化(定義且宣告)(因為類內部都是宣告)

可以用物件來訪問 也可拿作用域來訪問靜態成員變數 不依賴與物件(物件可有可無)

 

Static 修飾成員方法:

  1. Static修飾的成員方法沒有this指標 所以靜態成員方法不能訪問普通的成員變數 (因為普通成員變數訪問是通過this指標找到物件 根據物件找到記憶體塊 而靜態成員方法沒有this指標 因此就沒有物件 就更不能訪問物件記憶體了)== > 呼叫約定為——cdecl 不依賴物件呼叫;

普通成員方法呼叫的約定為thiscall依賴於物件 儲存著物件的地址)

  1. 靜態的成員方法不依賴物件呼叫(物件可有可無)
  2. 靜態成員方法能訪問靜態成員變數,靜態成員方法也能訪問全域性變數(因為全域性變數跟物件也沒關係 靜態成員方法不依賴於物件)
  3. 靜態成員方法不能呼叫普通的成員方法(因為普通的成員方法是依賴於物件呼叫的 靜態成員方法沒有this指標 沒有物件 所以無法呼叫)
  4. 普通成員方法能呼叫靜態成員方法

 

六.給出以下程式碼:為什麼呼叫點在定義之前也能呼叫成功呢?

class Test

{

   void show()

{

     Show(ma);

}

   void show(int a)

{

}

};

針對C++類 編譯器是這樣掃描的

  1. 掃描類名
  2. 掃描類成員名稱(函式名 變數名)編譯器已經知道了有這兩個show函數了
  3. 掃描形參 預設值 和方法體