C++學習筆記 this指標,物件陣列,物件指標陣列;
一,this指標
this指標不是物件的一部分,this指標所佔的記憶體大小是不會反應在sizeof操作符上的,this指標的型別取決與使用this指標的成員函式型別以及物件型別
也是一個const指標,它的值是不能被修改的,它指向當前物件,通過它可以訪問當前物件的所有成員;
this只能用在類的內部,但只有在物件被建立以後才會給this賦值,並且這個賦值的過程是編譯器自動完成的,使用者不能顯式賦值。
通過this可以訪問類的所有成員,包括private,protected,public屬性的。this是一個指標,要用->來來訪問成員變數或成員函式
this到底是什麼?this實際上成員函式的一個形參,在呼叫成員函式時將物件的地址作為實參傳遞給this,不過this這個形參時隱式的,它並不出現在程式碼中,而是在編譯階段由編譯器預設地將它新增到引數列表中。同時成員函式和成員變數關聯的橋樑。
注意:友元函式沒有this指標,因為友元不是類的成員,只有成員函式才有this指標;靜態成員函式沒有this指標。
二,物件陣列
1 class M 2 { 3 public: 4 M(int i,int j) 5 { 6 m = i; n = j; cout << "Constructor Called!" << endl; 7 } 8 M() { m = n = 0; cout << "Default Constructor Called!" << endl; } 9 10~M() { cout << "Destructor Called!" << m << "," << n << endl; } 11 int Getm() { return m; } 12 int Getn() { return n; } 13 14 private: 15 int m, n; 16 }; 17 M mm1[2]; 22 int main() { 23 M mm2[4] = { M(2,3),M(5,6),M(7,8),M(2,5) }; 24 M a = M(10, 100); 25 mm1[0] = mm2[0]; 26 mm1[1] = M(50, 90); 27 cout <<"mm1[0]=(" << mm1[0].Getm() << "," << mm1[0].Getn() << ")" << endl; 28 cout << "mm1[1]=(" << mm1[1].Getm() << "," << mm1[1].Getn() << ")" << endl; 29 for(int i=0;i<4;i++) 30 cout << "mm2["<<i<<"] = (" << mm2[i].Getm() << ", " << mm2[i].Getn() << ")" << endl; 31 32 33 return 0; 34 }
陣列其實也可以容納複雜的資料型別,比如程式設計師定義的結構或物件。這一切所需的條件就是,每個元素擁有相同型別的結構或同一類的物件
1,陣列的元素可以時物件
2,如果在建立物件陣列時為使用初始化列表,則會為陣列中的每個物件呼叫預設建構函式
3,沒有必要讓陣列中的所有物件都使用相同的建構函式
4,如果在建立物件陣列時使用初始化列表,則將根據所使用引數的數量和型別為每個物件呼叫正確的建構函式
5,如果溝站是需要多個引數,則初始化必須採用建構函式呼叫的形式
6,如果列表中的初始化項呼叫少與陣列中的物件,則將為所有剩餘的物件呼叫預設建構函式
三,物件指標
每一個物件在初始化後都會在記憶體中佔有一定的空間。因此,即可以通過物件名訪問一個物件,也可以通過物件地址來訪問一個物件。
物件指標就是用於存放物件地址的變數。宣告物件指標的一般語法形式為:類名* 物件指標名;
(1)用指標訪問單個物件成員
- 定義指標變數:
Date *p,date1;
- 初始化:指向一個已建立的物件
p=&date1;
- 訪問:用“->”操作符,只能訪問該物件的公有成員。
(2)用物件指標訪問物件陣列
物件指標不僅能訪問單個物件,也能訪問物件陣列.
指向類的成員的指標
類的成員自身也是一些變數、函式或者物件等。因此,也可以直接將它們的地址存放到一個指標變數中,這樣就可以使指標直接指向物件的成員,進而可以通過指標訪問物件的成員。
可在類外定義指向類的成員的指標來控制物件的成員。
注意:
- 指向成員的指標只能訪問公有資料成員和成員函式。
- 使用要先宣告,再賦值,然後訪問。
(1)指向資料成員的指標
- 宣告:型別說明符 類名:: *資料成員指標名
- 賦值:資料成員指標名=&類名:: 資料成員名
- 使用
- 物件名. *資料成員指標名
- 物件指標名->*資料成員指標名
指向可訪問無歧義非虛基類的資料成員的指標,可以隱式轉換成指向派生類的同一資料成員的指標:
1 struct Base { int m; }; 2 struct Derived : Base {}; 3 4 int main() 5 { 6 int Base::* bp = &Base::m; 7 int Derived::* dp = bp; 8 Derived d; 9 d.m = 1; 10 std::cout << d.*dp << ' ' << d.*bp << '\n'; // 列印 1 1 11 }
相反方向的轉換,即從指向派生類的資料成員的指標到指向無歧義非虛基類的資料成員的指標,允許由 static_cast 和顯式轉型來進行,即使基類並無該成員(但當用該指標訪問時,最終派生類中有)亦可:
1 struct Base {}; 2 struct Derived : Base { int m; }; 3 4 int main() 5 { 6 int Derived::* dp = &Derived::m; 7 int Base::* bp = static_cast<int Base::*>(dp); 8 9 Derived d; 10 d.m = 7; 11 std::cout << d.*bp << '\n'; // OK:列印 7 12 13 Base b; 14 std::cout << b.*bp << '\n'; // 未定義行為 15 }
成員指標的被指向型別也可以是成員指標自身:成員指標可為多級,而且在每級可以有不同的 cv 限定。亦允許指標和成員指標的混合多級組合:
1 struct A 2 { 3 int m; 4 // 指向非 const 成員的 const 指標 5 int A::* const p; 6 }; 7 8 int main() 9 { 10 // 指向資料成員的非 const 指標,該成員是指向非 const 成員的 const 指標 11 int A::* const A::* p1 = &A::p; 12 13 const A a = {1, &A::m}; 14 std::cout << a.*(a.*p1) << '\n'; // 列印 1 15 16 // 指向 const 的成員指標的常規非 const 指標 17 int A::* const* p2 = &a.p; 18 std::cout << a.**p2 << '\n'; // 列印 1 19 }
語法 | 含義 |
---|---|
constT* | 指向 const 物件的指標 |
Tconst* | 指向 const 物件的指標 |
T*const | 指向物件的 const 指標 |
constT*const | 指向 const 物件的 const 指標 |
Tconst*const | 指向 const 物件的 const 指標 |
(2)指向成員函式的指標
- 宣告:型別說明符 (類名∷ *指標名)(引數表);
- 賦值:成員函式指標名 = 類名∷成員函式名;
- 使用
- (物件名.*成員函式指標名)(引數表);
- (物件指標名 -> *成員函式指標名) (引數表);
函式的指標是物件,從而能儲存與陣列,被複制,被賦值。
1 int f(int n){ 2 std::cout<<n<<std::endl; 3 return n*n; 4 } 5 6 int main(){ 7 int (*p)(int)=f; 8 int x=p(7); 9 10 }
解引用函式指標生成標識被指向函式左值;
1 int f(); 2 int (*p)() = f; // 指標 p 指向 f 3 int (&r)() = *p; // 將標識 f 的左值繫結到引用 4 r(); // 通過左值引用呼叫函式 f 5 (*p)(); // 通過函式左值呼叫函式 f 6 p(); // 直接通過指標呼叫函式 f