C++學(xué)習(xí)筆記之類(lèi)成員指針
C++的類(lèi)成員指針是一種奇葩的指針。
假設(shè)現(xiàn)在我們要表示一個(gè)三維的點(diǎn),現(xiàn)在有兩種定義方式:
struct point1{ int x, y, z; }; struct point2{ int c[3]; };
第一種的優(yōu)點(diǎn)是更直觀,但第二種可以方便的用for遍歷三個(gè)屬性。最終我選擇了第一種,但是我還想弄一個(gè)遍歷功能怎么辦?這個(gè)時(shí)候類(lèi)成員指針就排上用場(chǎng)了,我們可以創(chuàng)建一個(gè)“指向point中具體成員的指針”。
int A:: *member = &A::x;
讓member指針指向A中的成員x,且類(lèi)型是int,此時(shí)我們就可以通過(guò)member來(lái)訪(fǎng)問(wèn)x:
point1 tmp{4, 5, 6}; cout << tmp.(*member); //把member解引用,得到tmp::x,表示要訪(fǎng)問(wèn)x
所以我們定義一個(gè)數(shù)組,就可以迭代訪(fǎng)問(wèn)類(lèi)里的各種int屬性了
int A:: *member [] = {&A::x, &A::y, &A::z}; for (int i = 0; i < 3; ++i) cout << tmp.(*member[i]);
這個(gè)用途也可以放到成員函數(shù)上,構(gòu)建一個(gè)函數(shù)列表,順序調(diào)用。
這么個(gè)指針的行為跟一般的指針顯然不一樣,它不保存地址,而是保存一個(gè)“偏移量”,從對(duì)象地址開(kāi)頭到對(duì)象成員的偏移量。這玩意其實(shí)可以輸出:
struct A{ int a, b, c; }; main() { printf("%d%d%d", &A::a, &A::b, &A::c); //! 輸入為0, 4, 8 //! 當(dāng)然這玩意類(lèi)型不是int,printf直接將他以int解析輸出了,所以cout達(dá)不到效果 }
這樣類(lèi)成員指針的意義就很明顯了,假設(shè)一個(gè)A的對(duì)象t,那么t的地址&t
和a的地址&(t.a)
是相等的,而&(t.b)
要多出來(lái)4,&(t.c)
又要多出來(lái)4。每個(gè)對(duì)象的內(nèi)存構(gòu)造都是一樣的,這個(gè)類(lèi)成員指針就是獲取每個(gè)成員相對(duì)于頭地址的偏移量,這樣當(dāng)我使用t.*member
編譯器就知道是頭地址+4處的變量,并且是個(gè)int。
不過(guò)成員函數(shù)又不太一樣了。不同對(duì)象的成員函數(shù)只有同一份程序短代碼。C++不能用&(t.fun)
的方式獲取對(duì)象的成員函數(shù)的地址,要用取&A::fun
得到函數(shù)的地址。這個(gè)當(dāng)然是真地址了。
類(lèi)成員指針可以用于static
嗎?顯然不行,static成員單獨(dú)存放,與類(lèi)本身無(wú)關(guān),取&A::staticmember
得到的就是這個(gè)變量的正經(jīng)地址。那可以用于virtual function
嗎?答案是可以,但是虛函數(shù)的地址無(wú)法確定,所以又變成了儲(chǔ)存偏移量,實(shí)際上儲(chǔ)存的是函數(shù)在虛表中的索引值。
補(bǔ)充:mem_fn
通過(guò)mem_fn對(duì)類(lèi)函數(shù)成員指針進(jìn)行包裝,來(lái)返回一個(gè)可調(diào)用對(duì)象。使用時(shí),包含頭文件functional。
#include <iostream> #include <functional> using namespace std; class Compute { public: Compute(int a, int b) :a(a), b(b) { } int add() { return a + b; } int sub() const { return a - b; } private: int a; int b; }; int main(void) { Compute com(100, 10), *p = &com; auto fun1 = mem_fn(&Compute::add); cout << fun1(com) << endl; cout << fun1(p) << endl; auto fun2 = mem_fn(&Compute::sub); cout << fun2(com) << endl; cout << fun2(p) << endl; cin.get(); return 0; }
運(yùn)行
總結(jié)
到此這篇關(guān)于C++學(xué)習(xí)筆記之類(lèi)成員指針的文章就介紹到這了,更多相關(guān)C++類(lèi)成員指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言單雙線(xiàn)性及循環(huán)鏈表與實(shí)例
這篇文章主要介紹了C語(yǔ)言的單鏈表、雙鏈表和循環(huán)鏈表,還有一些相關(guān)的實(shí)例,感興趣的同學(xué)可以借鑒一下2023-03-03c++ 動(dòng)態(tài)內(nèi)存分配相關(guān)總結(jié)
這篇文章主要介紹了c++ 動(dòng)態(tài)內(nèi)存分配相關(guān)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)和使用c++,感興趣的朋友可以了解下2021-02-02C語(yǔ)言實(shí)現(xiàn)單鏈表實(shí)現(xiàn)方法
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)單鏈表實(shí)現(xiàn)方法的相關(guān)資料,鏈表分為單向鏈表、雙向鏈表、循環(huán)鏈表,需要的朋友可以參考下2017-08-08C語(yǔ)言中的內(nèi)存泄露 怎樣避免與檢測(cè)
堆經(jīng)常會(huì)出現(xiàn)兩種類(lèi)型的問(wèn)題:1.釋放或改寫(xiě)仍在使用的內(nèi)存(稱(chēng)為:“內(nèi)存損壞”)。2.未釋放不再使用的內(nèi)存(稱(chēng)為:“內(nèi)存泄露”)。這是最難被調(diào)試發(fā)現(xiàn)的問(wèn)題之一2013-09-09C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單計(jì)算器
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易訂餐系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易訂餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06詳解C語(yǔ)言解決經(jīng)典問(wèn)題之兔子產(chǎn)子
有一對(duì)兔子,從出生后的第 3 個(gè)月起每個(gè)月都生一對(duì)兔子。小兔子長(zhǎng)到第 3 個(gè)月后每個(gè)月又生一對(duì)兔子,假設(shè)所有的兔子都不死,問(wèn) 30 個(gè)月內(nèi)每個(gè)月的兔子總數(shù)為多少?本文將用C語(yǔ)言解決這一經(jīng)典問(wèn)題,需要的可以參考一下2022-03-03