網(wǎng)站首頁 編程語言 正文
C++的類成員指針是一種奇葩的指針。
假設(shè)現(xiàn)在我們要表示一個三維的點(diǎn),現(xiàn)在有兩種定義方式:
struct point1{ int x, y, z; }; struct point2{ int c[3]; };
第一種的優(yōu)點(diǎn)是更直觀,但第二種可以方便的用for遍歷三個屬性。最終我選擇了第一種,但是我還想弄一個遍歷功能怎么辦?這個時候類成員指針就排上用場了,我們可以創(chuàng)建一個“指向point中具體成員的指針”。
int A:: *member = &A::x;
讓member指針指向A中的成員x,且類型是int,此時我們就可以通過member來訪問x:
point1 tmp{4, 5, 6}; cout << tmp.(*member); //把member解引用,得到tmp::x,表示要訪問x
所以我們定義一個數(shù)組,就可以迭代訪問類里的各種int屬性了
int A:: *member [] = {&A::x, &A::y, &A::z}; for (int i = 0; i < 3; ++i) cout << tmp.(*member[i]);
這個用途也可以放到成員函數(shù)上,構(gòu)建一個函數(shù)列表,順序調(diào)用。
這么個指針的行為跟一般的指針顯然不一樣,它不保存地址,而是保存一個“偏移量”,從對象地址開頭到對象成員的偏移量。這玩意其實(shí)可以輸出:
struct A{ int a, b, c; }; main() { printf("%d%d%d", &A::a, &A::b, &A::c); //! 輸入為0, 4, 8 //! 當(dāng)然這玩意類型不是int,printf直接將他以int解析輸出了,所以cout達(dá)不到效果 }
這樣類成員指針的意義就很明顯了,假設(shè)一個A的對象t,那么t的地址&t
和a的地址&(t.a)
是相等的,而&(t.b)
要多出來4,&(t.c)
又要多出來4。每個對象的內(nèi)存構(gòu)造都是一樣的,這個類成員指針就是獲取每個成員相對于頭地址的偏移量,這樣當(dāng)我使用t.*member
編譯器就知道是頭地址+4處的變量,并且是個int。
不過成員函數(shù)又不太一樣了。不同對象的成員函數(shù)只有同一份程序短代碼。C++不能用&(t.fun)
的方式獲取對象的成員函數(shù)的地址,要用取&A::fun
得到函數(shù)的地址。這個當(dāng)然是真地址了。
類成員指針可以用于static
嗎?顯然不行,static成員單獨(dú)存放,與類本身無關(guān),取&A::staticmember
得到的就是這個變量的正經(jīng)地址。那可以用于virtual function
嗎?答案是可以,但是虛函數(shù)的地址無法確定,所以又變成了儲存偏移量,實(shí)際上儲存的是函數(shù)在虛表中的索引值。
補(bǔ)充:mem_fn
通過mem_fn對類函數(shù)成員指針進(jìn)行包裝,來返回一個可調(diào)用對象。使用時,包含頭文件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é)
原文鏈接:https://www.cnblogs.com/ofnoname/p/16172357.html
相關(guān)推薦
- 2021-12-09 C/C++?Qt?Tree與Tab組件實(shí)現(xiàn)分頁菜單功能_C 語言
- 2024-02-26 Cannot execute binary file 之原因
- 2022-11-05 nginx修改默認(rèn)端口方法圖文詳解_nginx
- 2022-08-15 初步了解MyBatis的相關(guān)配置
- 2022-09-09 C語言中回調(diào)函數(shù)和qsort函數(shù)的用法詳解_C 語言
- 2022-09-16 Pandas數(shù)值排序?sort_values()的使用_python
- 2022-09-26 ASP.NET?MVC打印表格并實(shí)現(xiàn)部分視圖表格打印_實(shí)用技巧
- 2022-06-01 docker安裝nginx并配置ssl的方法步驟_docker
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支