' b$ V6 E" u" M% q3 ?. k假设有一幅RGB图像720*576个像素,每个像素有RGB三个通道,每个通道的值是8bit大小。给出图像的首地址p_rgb_image, 我们要取第40行,第50个像素的R,G,B值。代码如下: & H4 `' |; N, T7 E/ x 2 ~9 `/ Z) c% N. e- Q5 A3 hunsigned char* p_rgb_image;) j9 u4 F8 M" j* C: S0 I8 e8 O' W, N
unsigned char r = p_rgb_image[40*720*3 + 50 + 0];( H+ A+ [* U; y; M
unsigned char g = p_rgb_image[40*720*3 + 50 + 1]; . T& _$ r" ~! h$ Uunsigned char b = p_rgb_image[40*720*3 + 50 + 2]; 3 M) ^/ d( x3 U+ S类似这样的场景, 采用多维数组的写法, 有点类似以索引为参数,可读性更高。相当于程序员和编译器打了一个配合。4 M' q& _4 l4 r& Q8 B1 p
B, L+ `; u6 u* M# G9 |/ q Y4 g
enum. I+ \" U) F" L& `3 S' U; p9 v( ], K
{, |* T$ e& H' M0 n) R) N, p
Red = 0, % b, A G6 k: c) g Green = 1, : U3 i/ j7 }: o" o3 E Blue = 2 1 T3 _( I" _% @, C, Y& P' ]};) P$ I2 a+ I# B9 A; t0 Z8 H6 e
unsigned char rgb_image[576][720][3];% w% Y2 a; h3 f& ]' }9 W3 T& k
int row = 40; 2 l8 k9 ]$ o9 h0 u5 M7 gint col = 50;& H; H- V/ N( x4 e9 }; | w8 ~
unsigned char r = rgb_image[row][col][Red];% D/ t- s p$ g9 }3 Q4 N) E
unsigned char g = rgb_image[row][col][Green];& ]% d# ?: z6 L* D; y. ~& k
unsigned char b = rgb_image[row][col][Blue]; ) A. G9 C- @- t- `: \) L m2 B数组指针以及与指针数组的区别 }6 Q* L: D: p! |* u5 f( Y8 i
数组指针,是一个指针, 指向的对象是数组。 数组指针的赋值,要求数组的长度匹配,否则会报错。当指向1维数组时, 需用用*取得数组对象的引用,再用下标来访问数组元素。" n# M$ F1 Y* D# s: @4 D* E0 G+ Z
指针数组,是一个数组, 数组保存的元素的类型是指针。# \/ B3 Y# C5 Z* e
数组指针的定义; C+ B$ }" ^7 Q6 a( J
数组指针定义先定义一个数组。7 D6 X4 Z# |0 W
int a[10];8 Q# ~( T/ d" k6 w; q R! O" P4 U
然后对数组里的名称用括号括起来后再在变量名称前面加个*号6 C+ p! P4 _5 \$ N/ c/ _+ F$ B3 Q4 S6 |
int (*a)[10]; ' P, H9 ~; b. ?+ Y: G后面你会发现函数指针定义类似。# o$ Q2 L- I. f! \1 s8 I; ~
// 各类定义对比 $ N) o9 a& D) ]/ wint a, *b, **c, d[10], e[10][20], *f[10], (*g)[10], *(*h)[10];% Z6 i% h! ]& v7 Z! X/ j# n4 n
# E! U0 D. D) \) M& R) _int *f[10]; // 指针数组, f是包含10个元素的数组, 数组里每一个元素的类型都是int*1 u1 B, b2 g/ `3 y1 V* a: W
int *(f2[10]); // 指针数组。另外一种定义方式。 / [( u- i) T% C# eint(*f3[10]); // 指针数组。另外一种定义方式。 ( f# x3 O1 F( }4 }& jint(f4)[10]; // int数组7 }; ]. J: n% _; w6 d1 a% }
int(*g)[10]; // 数组指针, g是一个指针, 这个指针可以指向类型是int,元素个数是10的数组6 c ?* M/ M2 i8 f1 E
int* (*h)[10]; // 数组指针, h是一个指针, 这个指针可以指向类型是int*,元素个数是10的指针数组 ( c8 Q" k7 m. L/ T0 M* D. j: P; ?+ C2 R) b. c! R
int d[10]; % S1 V$ a5 S/ dg = &d;2 J- H* l! v5 l, L9 Q- T
8 k( E/ P+ y2 a/ Q% d$ s# Y$ P) z
int* e[10]; , U b, m) }: _8 a$ T sh = &e;/ U& g5 {. n! A. ~
数组指针的使用$ }9 y: h& k/ H+ V7 S3 D
数组指针一般先通过*号取得指针指向的数组对象, 然后再用下标操作访问元素。! z/ x# a' |2 u( ~4 J* h8 \# [# |, X$ |
( _6 ?3 ]) O& R% f# [2 X* R
int a[10]; - S8 g+ {6 O h0 w, Aint(*p_ary)[10] = &a; // p_ary是一个指针, 指向"int (*)[10]"类型的数组2 @# z3 W. s. V. E* S: i" H5 D* l
for (int i = 0; i < 10; i++) { 3 z0 H5 y, q% G9 l( x // p_ary是一个指向数组的指针, 需要先通过间接寻址运算符*(indirection operator)取得数组对象 ! }5 b+ X) l% u) V8 f" h* Y ~ // 再通过下标操作访问元素。 6 e9 p2 N6 T" a0 p4 m (*p_ary) = i; ; b: @' j9 z0 n
}, a; @- Q' g# m% F& `
, q& O3 I& b# m! K$ `
int b[10];* o4 `! \7 c& W6 ]" L
int c[20]; ' c( ~; d/ t" V/ L$ w' Fp_ary = &b; // 合法# k, z' j, ]& U
p_ary = &c; // 报错! 不能将 "int (*)[20]" 类型的值分配到 "int (*)[10]" 类型的实体 . @+ y. v* q+ W, i数组指针指向多维数组的子数组 ) E! g' U1 G8 W; T: O5 h4 pint a[10]; & o1 f$ D/ z5 x% Y1 j& y kint b[4][10];9 v; H4 P: m5 {, i' d
int(*p_ary)[10] = &a; ) }; A, d8 T# U n$ M. efor (int i = 0; i < 10; i++) {" S, p5 S) o; u
(*p_ary) = 1; 4 o- m/ S7 y& d4 z7 Q0 ?' O} % y/ f, _) B0 ?% t- b% h " z8 V( J* R: {* y* M3 }p_ary = &b[2]; // 多维数组,可以看作数组的数组,2 h& Y9 [- {4 k9 h! l, ?$ ~1 ^* C4 Q
// b[2][0] ~ b[2][9]的值都被改成2了7 p3 V) q% Z& M$ L& K3 H
for (int i = 0; i < 10; i++) {0 r. g, j; {6 U
(*p_ary) = 2;& g/ k, r( `$ s3 t9 ^# W4 c
} 7 S8 K! B6 h2 j! K, b, N8 H多维数组指针5 T/ [- ]3 i" G( q
多维数组指针,是一种指针,指向的对象是个多维数组,支持多个下标操作。4 F" Y) o+ r: K7 e, [
9 w3 L5 I; K- m/ @$ h1 `int a[2][5][10]; : M p8 ^& g! Z% {4 b$ ^int(*p_ary1)[10] = &a[1][2]; // 1维数组指针; }' d. O. x# H3 k% f' w6 }
int(*p_ary2)[5][10] = &a[1]; // 2维数组指针 $ `1 e* a1 r/ `; ~; R" c$ gfor (int row = 0; row < 5; row++) { 5 Z9 @/ ?! x# ?9 [: a for (int col = 0; col < 10; col++) { ' { m- t6 u/ r' E (*p_ary2)[row][col] = row * col; 5 S/ f$ u& M3 K } - k' k7 }4 g4 G5 P+ p3 n& [} E. `" ]4 K9 Z3 z, u
数组指针和指针数组对比实例8 F) ^, U, p8 D- T' L0 S
数组指针还是记住两步法即可 # {+ |% W/ I) d+ [5 P1 h7 t) P% ?: U2 m4 A7 |0 X s
定义一个数组& i' J- W& \3 G8 `
括号包围1中定义的名称,再在名称前加个*号。* r5 s/ s5 n6 @
int a[10];6 ^" l) W" `) ]& g2 q5 O+ b
int(*ary_pointer1)[10] = &a; // 数组指针 " F! E) {, U% M2 R8 f- _int* pointer_ary1[10]; // 指针数组。元素类型是int*% t) z, N; Q% D6 u3 }% t1 }
int *(ponter_ary2[10]); // 指针数组。另外一种定义方式。 . i q! B, c! Z$ o X. R5 `7 Kint (*ponter_ary3[10]); // 指针数组。另外一种定义方式。- p. z9 X' U0 y) H
int c, *d, (*ary_pointer2)[10], *pointer_ary3[10]; // 排列定义比较。 g# D, t' T" G% J ; c4 y; A, ^7 e* G: `5 q// 指针数组可以把每个元素指向数组对应位置的地址。 , s9 I( d! Y7 A* A// 这样遍历指针数组, 可以达到遍历数组元素的效果,但是注意每个元素都是指针,; H/ n. ^& @' m% |" h
// 需要访问原数组的值的话, 需要对指针用*间接寻址运算符。# z8 W* B( o; }2 \4 k% Q2 P
int* pointer_ary[10]; * h: Z( @+ \1 ^. S: lfor (int i = 0; i < 10; i++) {/ }% F1 C6 s5 v4 O2 I- {% j" ^
pointer_ary = &a; 9 \- C* S8 T0 ]} ) c8 v3 c/ c1 [// 类似遍历原数组效果。 # t3 ?3 _9 ~& L+ Vfor (int i = 0; i < 10; i++) { * G' }; m7 ^4 e) b( W *pointer_ary = i; // 修改原数组。% ?# _/ M$ ^% g! m8 q
}, p% l, D+ Z+ @1 d8 \) A# F9 A/ S
d1 F3 J& t. r9 z" ~ B3 V. S
函数指针 6 z! q C% V7 S1 z6 e取得函数地址 6 i. ? K M$ I& R0 N6 @! r, ~函数的名称作为参数被传递时,会隐式转换成函数指针, 和在函数名称前加取地址符&等价。建议带上更加统一和清晰。 , t# w" H$ M4 s2 H) C6 @( \7 @4 e8 O$ ?: \ t& {5 }; ^
void f(int); c0 z- }9 v8 v) c; n6 {) `1 T" nint main()5 C# W4 Q( \& l& t, L
{ 2 W2 f. y- E+ g0 J% o void (*p1)(int) = &f;" E$ q; m+ |9 p8 [6 h2 D; {
void (*p2)(int) = f; // same as &f6 c) z& }: b9 {: `3 d
return 0;5 e* F' D% G. f/ D5 A. F7 w
} 4 q. A) O7 s" U* ~4 i7 P翻译成汇编代码, p1和p2的赋值是一样的。7 E6 I5 J6 x3 X+ s0 r. S
- g3 j6 o. L+ v; g# u
, `1 `# `8 f" X4 f, B% A2 V + e" F, y) w( Y5 r; j; ]! V函数指针的声明1 `! j, U. v) ~8 j |& w. _
单个函数指针变量定义步骤 / D# Z: R( w9 y0 e. S$ r+ S定义一个函数。void fun1(int a, int b); int fun2(double a);& @4 Y9 ?6 Q; p
用括号把函数名称包围起来,然后在名称前面加*号。void (*fun1)(int a, int b); int (*fun2)(double a);3 f8 K6 O0 }3 T: X0 {( p: \8 b ]0 C
如果要定义函数指针数组,在定义单个函数指针的基础上,在名称后面加上[数组长度]void (*fun1[2])(int a, int b); int (*fun2[10])(double a);; v5 R$ r2 E, M
typedef定义函数指针; ~: B2 e! X0 q2 _4 j
可读性高比单个定义要高,特别是声明多个同类型的函数指针,或者函数指针数组。0 C6 p3 y. T$ l+ P* h; ?2 j8 e
8 `7 x' Z* T4 }0 q/ G4 B9 ^. A5 rtypedef定义函数指针的语法# A, Q3 O/ P S* F8 X3 F
typedef有两种做法, 一种就是定义一种函数对象,另外一种就是定义函数指针。用法稍稍不同,效果是一样。其中函数对象不支持赋值, 但是支持引用。0 `: H, ^$ T, ]1 a2 ~, F8 x
4 D5 R; ]8 [& _7 U! n* h' j7 \typedef int FuncObject(int a, int b); // FuncObject类型是函数对象6 {- n6 u, J, u9 o/ c4 B& T3 h7 f
typedef int (*FuncPointer)(int a, int b); // FuncPointer类型是函数指针 # \5 U) C7 A" l5 C a' a" V* J' WFuncObject* f1 = &Add;; \' V1 X l" U. F
FuncPointer f2;8 e; F, t6 \5 N. E
f2 = f1; // f1, f2类型一样, 都是形式为int(int, int)的函数的指针。0 q$ X6 S0 Z6 C2 S$ M' c1 x2 O
FuncObject f3 = Add; // 报错! 函数对象不支持拷贝 / U3 D, D( R- z0 b% l+ i4 o. VFuncObject f4 = &Add; // 报错!&Add是函数指针,与函数对象类型不匹配 & m; F4 `# R2 r ^5 j- u( HFuncObject& f5 = Add; // 正确 $ V; X3 N) s: y$ a" p! qint ret = f5(2, 3); // 正确 & L5 a# w' B+ Q. }6 cFuncObject& f6 = &Add; // 报错!&Add是函数指针,与函数对象引用类型不匹配/ U% F* t3 L! z4 g- i
如何记住typedef定义函数指针的步骤. F: X1 z2 [, w9 L e% e
像定义一个函数指针那样, 指定一个名称。int (*CalFun)(int a, int b); 5 @. B# |$ K$ E1 P6 e7 N在这个函数指针变量声明前面加上typedef。typedef int (*CalFun)(int a, int b);: A1 a h/ }; A8 P" x& P
完整例子0 B7 Z5 b* p" }& t E
typedef int(*CalFun)(int a, int b); 6 `5 }* E/ X+ B, p ; @) R) }. A4 D( @: Jint Add(int a, int b)& r; q+ Q- O: h
{ # r. |: n* J. t7 X" j/ R+ i, v( G return (a + b);$ I' m7 }8 F* a
} 1 r5 L% W3 k( G: q6 ?+ A2 v1 f2 L1 @/ o+ I4 r+ @6 h
int Sub(int a, int b): F7 r$ T1 a' k
{ . n& o* `# n; N( R return (a - b); $ k) W$ R' r/ ?$ d} " d+ `; n& {' C; ]# {- O9 }. Q* a* P2 r9 J4 C2 l2 G9 b
int main(int argc, char** argv); u3 r0 e6 |) c& x1 l
{" s2 F- q3 ~3 J2 X+ r$ V. z7 b
CalFun f1 = Add; ! z- Q8 t9 j/ q CalFun f2 = Sub;$ ~, G* Z2 ?4 a9 T8 O! c, F0 t
int a = f1(2, 3);) j8 b0 t. x8 i* v. r6 {$ l
int b = f2(10, 5); / f% X4 ^) ~8 m' E9 `) | , S) Q9 j% x: l0 W) I // typedef定义的函数指针数组。2 P) K+ p, u. i" M. `3 D
CalFun f_ary[2]; : \. K, R+ | {& v a+ J f_ary[0] = Add;4 d: U. Q3 p& c" t( K, N
f_ary[1] = Sub; & q7 s7 d9 ]1 x* t ! U# S# |' z1 h // 单个定义的函数指针数组。! r0 `+ l3 |4 X/ w) e
int(*f_ary2[2])(int a, int b); ' R" D l) j9 n, n' A" K f_ary2[0] = Add;1 S6 R1 f$ ^ Y) I6 L& ?
f_ary2[1] = Sub; 0 ?! W H& W# ~0 O' t) e , I1 u" {6 r8 G. t# i( j return 0; 9 |6 d# q! w8 @+ m% v5 K. a. f* f} ( }% }2 F5 M S3 @# t! h9 e$ B/ y S% m S
using别名定义函数指针 4 O: A, M. Z1 zc++11以后的类型别名定义--using也可以用于定义函数指针, typedef的好处它都有,个人感觉比typedef更直观。using类型别名同样分函数对象和函数指针两种方式。 4 j. c+ b6 G0 x) q) Z# Y1 J7 i) {. l5 S0 W0 w
typedef int FuncObject(int a, int b); // FuncObject类型是函数对象# q& h6 x9 k7 J7 H
using FuncObject = int(int a, int b);7 k8 C- b1 e. b! p" }
typedef int (*FuncPointer)(int a, int b); // FuncPointer类型是函数指针 ' F q, A! A L) o P* y$ z) |using FuncPointer = int(*)(int a, int b);, Y2 X5 X" I7 {# X. Y' i
函数指针的调用 + D' _0 F' Z0 J. {函数指针和函数对象都可以直接后加括号调用 P/ a* l2 I) }* `4 {3 ?
int f(); ; r7 d- [( p; _) E/ Iint (*p)() = f; // pointer p is pointing to f 1 X& j4 p' L+ {# Q, G- rint (&r)() = *p; // the lvalue that identifies f is bound to a reference- v1 P& K" s; Y5 `' n9 F7 d
r(); // function f invoked through lvalue reference2 D) @$ z* a5 u d1 q( x4 z' t
(*p)(); // function f invoked through the function lvalue# {0 n( k2 P: [, j: ?! a
p(); // function f invoked directly through the pointer& b! }3 p2 p3 s( M2 F4 m
如果函数有重载, 函数指针会指向匹配的那个版本。' x( a: d5 P; L
template<typename T>$ I" ?% G! T+ B V
T f(T n) { return n; }- A# ~' P, V/ c$ R7 o: f# }7 [
; F7 r/ H" T" Y8 tdouble f(double n) { return n; } 1 ?6 G9 _ b; K: ^$ l9 q& ` - ]& p$ [/ [; N% O" Zint main() & r; j5 l4 R+ Q* n{9 B- l: K5 e7 T7 o% c- V9 j
int (*p)(int) = f; // instantiates and selects f<int>2 R) E2 B) u3 m' }& ]& i
} % X) v# I) e5 f7 _3 _4 E成员函数指针 % ]4 N& a' r) \" x/ B5 M! J静态成员函数,除了增加了访问控制以外,跟普通的函数指针没什么区别,所以普通函数指针可以直接指向类的静态成员函数。但非静态的成员函数与普通函数指针不太一样,声明时需要指定函数归属的类名,并且调用需要指定对象实例。: }+ M: a, |3 o5 k
1 ]/ M* K% x3 o5 g9 m6 A5 C
成员函数指针定义。7 D& \( I4 y/ S& |0 D1 j
像定义类成员函数实现那样写, 并任意指定名称,这里作func。void ClassName::func(int);$ C' d) Z3 Z& b! k5 I! U3 [. E0 e5 i
括号把类名、范围解析运算符::、名称包围起来。void (ClassName::func)(int);6 d" @7 b: M' {% h% Q5 |8 L
在名称的前面加个*号void (ClassName::*func)(int); T9 B' M, T0 M成员函数也支持typedef和using的定义方式。typedef void(C::* MemberFunc)(int); using MemberFunc = void(C::*)(int);! t4 f) B: X: g
成员函数指针如何调用。. q9 Z7 y0 u! u2 ^1 Q
假设成员函数指针名字为func( R# m+ Q, t9 E5 H( \" w
3 n. B" {9 U# N, Qvoid (ClassName::*func)(int); 4 y, h' f( L1 j1 }对象式调用。$ m8 {, b6 j, c* Z6 A) |
ClassName c; // 被调用的对象5 o$ G% ~$ T0 T- i/ `
成员函数指针名字当作正常函数那样写。 + e' V; |4 I0 D# H$ u, k* I5 u! oc.func(3); & s* f$ m0 e& y, P3 j* j& o8 ` _成员函数指针是指针, func名称前面需加上间接寻址运算符*,变成函数对象。 : X+ l# l* z; v( V* S$ Dc.*func(3); ) f( `6 N6 ^4 @最后用括号把调用对象、成员访问运算符.、间接寻址运算符*、和成员函数指针的名称包围起来。 7 O& k/ ` Q* ^* @3 e* L8 M5 K(c.*func)(3);( \' o% R1 U* \; ]! S
为何要加上括号? 根据c++的优先级标准,取成员运算符. > 函数调用() > 间接引用符*。 *号优先级比函数调用要低, 成员函数指针还没取得对象就被调用了,自然报错。 另外 - X! A" p6 q2 v, e. N* I+ d" r(c.(*func))(3);3 _6 e6 G9 a. T4 _! R/ a
这样的写法也不行。 .*和->*是整体作为一个运算符的,中间不能用括号隔开。 & ^2 j y0 G0 g1 E, p4 ?8 ]% X( l5 m指针式调用 ' p. \ f J: u% VClassName* p; // 被调用的对象的指针; {/ W& E; Z) i1 R. a
成员函数指针名字当作正常函数那样写。9 A/ c6 d" S/ W4 q, t$ }
p->func(3); ; z. \( e' g2 L; a7 U成员函数指针是指针, func名称前面需加上间接寻址运算符*,变成函数对象。 ; N: m9 l' z+ R$ lp->*func(3);" Z8 D/ X2 x" q2 L# A5 E" O
最后用括号把调用对象、成员访问运算符->、间接寻址运算符*、和成员函数指针的名称包围起来。( T5 G& j6 \6 @5 N
(p->*func)(3);& `: G2 }* ~7 ]
函数指针使用完整例子 6 B2 J- x7 D# O# l- H m* qstruct Cal - } c8 r2 Y, v{ 2 G- ^/ k0 n h% i. I2 Z) L
int add(int a, int b); 4 f/ z6 {9 P% D, H# y1 s
int sub(int a, int b);, d3 A& q2 m- z
};7 H, q) K! H* d& m1 T( J
( A T* a* T. O% w, S% ?3 m
int main() 6 ^/ U5 `' a8 t# b{- ^' @ l# k: a
int (Cal::*fun)(int, int) = &Cal::add; , d+ t% C) W7 W0 `% |, C fun = &Cal::sub;% ^4 \" @4 L4 P) B: O: |5 T0 \
/ Q+ j( u, _2 G! f
Cal* p_cal = new Cal();9 M4 m b. Z6 i, ?* o
int r1 = (p_cal->*fun)(2, 3); " ?. }7 s4 N' E% V6 H delete p_cal;& b3 Z$ c# Y5 x7 G( b4 ^
% O6 a8 c- G4 j) b Cal local_cal; 8 W/ }( p% B. V2 i% u0 b# D int r2 = (local_cal.*fun)(8, 6); 0 H# ?" S$ ~3 E8 w$ K, ~, N8 k$ F, `; v" v} ! Z) T: O0 |* Y4 H8 j! V # U* _4 k6 ~: Q7 w! D( J; N成员变量指针 , m' N/ `9 X. P# O) Y& O成员变量指针比成员函数指针还要简单些,没有函数调用, 无需考虑函数调用和间接引用符*的优先级问题。 6 ?8 E! T' n7 w) }& ~& { ( Q" l# @, a W. _; n( q成员变量指针的定义5 y( G& q9 K2 v0 F8 o/ H
假如以下结构体C。 - q5 j* X( w3 g# k9 Z7 K0 K7 i9 E, m8 d
struct C 5 O* b( l( i" ?# c: ^1 Y{ ' W' E. g# Q' a int m; . i5 R8 F2 J4 {+ V& n}; 2 I& w$ r. B% u5 q* N1 e( y* D单个成员变量指针定义 3 F' r( m$ n3 o: D
假设名称为p, 类似静态成员变量定义那样声明 * R! n( v6 o9 e' O. Sint C::p;, |* i# L, h0 p6 Z) v( I# p) R' |
在名称前面加上指针标识号* 7 {# N# D E% ]" m1 V! Dint C::*p;9 t7 Q2 s3 K1 J' ]' e) U
typedef或using方式定义3 z( M; S: h4 p7 b; [5 r
typedef int C::*MemberPointer;. b7 n1 I6 F9 Q; _# {+ I
using MemberPointer = int C::*;0 O: s) m$ r8 l/ E k
成员变量指针的使用。 ) c: g. q1 ]3 t0 t1 r类似成员函数指针那样,直接使用指向成员的指针运算符:.* 和->*即可。/ a2 N& g" ]0 |4 a" G* S& G
成员变量指针, 能让我们实现一些遍历成员的动态功能。 例如把一个类/结构体的多个同类型的成员变量放进一个容器里,然后遍历访问这些成员变量。 - b$ o& ?8 t: ^! i) m* P) T- I2 _9 A( Q# Z- e
完整例子$ m4 I0 j. e- ? M) N ]7 K
struct C { int m; };' W1 r! w& k2 O4 x. X. O/ G
int main() 1 C: L# P/ _# e4 W+ h8 y4 b{ - A' U9 b& h! Z: L0 q3 E int C::* p = &C::m; // pointer to data member m of class C" h2 r6 }& H* V4 ]
C c = {7}; 6 L2 G2 A+ S! j std::cout << c.*p << '\n'; // prints 7 2 M: y# W2 K; r- Z% d C* cp = &c; . z6 k- o5 `! [' i) K5 ?. S1 [ cp->m = 10; w9 J, _6 ]' ?) E9 c! n, q, G std::cout << cp->*p << '\n'; // prints 10 : I( x. x- O3 [- C ]6 _( R. t6 Q o
————————————————6 s4 a5 ? [! \. a
版权声明:本文为CSDN博主「南风fahaxiki」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。3 a6 c6 Y' m( j+ ^
原文链接:https://blog.csdn.net/m0_64407685/article/details/126788115 8 y/ |4 p) ]! i+ \0 L ; g( Y* S( I* A# O: o , o" J- R3 c4 Q* G; P2 G