類和物件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 修飾成員方法:
- Static修飾的成員方法沒有this指標 所以靜態成員方法不能訪問普通的成員變數 (因為普通成員變數訪問是通過this指標找到物件 根據物件找到記憶體塊 而靜態成員方法沒有this指標 因此就沒有物件 就更不能訪問物件記憶體了)== > 呼叫約定為——cdecl 不依賴物件呼叫;
(普通成員方法呼叫的約定為thiscall依賴於物件 儲存著物件的地址)
- 靜態的成員方法不依賴物件呼叫(物件可有可無)
- 靜態成員方法能訪問靜態成員變數,靜態成員方法也能訪問全域性變數(因為全域性變數跟物件也沒關係 靜態成員方法不依賴於物件)
- 靜態成員方法不能呼叫普通的成員方法(因為普通的成員方法是依賴於物件呼叫的 靜態成員方法沒有this指標 沒有物件 所以無法呼叫)
- 普通成員方法能呼叫靜態成員方法
六.給出以下程式碼:為什麼呼叫點在定義之前也能呼叫成功呢?
class Test
{
void show()
{
Show(ma);
}
void show(int a)
{
}
};
針對C++類 編譯器是這樣掃描的
- 掃描類名
- 掃描類成員名稱(函式名 變數名)編譯器已經知道了有這兩個show函數了
- 掃描形參 預設值 和方法體