C++数组指针、函数指针、成员函数指针 : H; u, m: [1 H0 x8 IC++数组指针、函数指针、成员函数指针+ o1 K1 c, O% Y$ `$ G2 c, ]9 s2 b
9 f% l$ z9 s. E4 T. J. `" T ; P t; L- L0 D- d, R2 h操作符名称9 Z& I# J# Y) w* d) i# f6 f
& 取地址符(Address-Of operator)6 c0 w2 j6 L+ O4 L* E' l
* 间接寻址运算符(Indirection operator) ' Q6 a# H# m7 A' a2 s+ V.和-> 成员访问运算符(Member-Access operators),用于取对象的成员。$ J% k2 V3 [! Q* E- T" p4 W
.*和->* 指向成员的指针运算符(Pointer-To-Member operators), 用于成员函数指针和成员变量指针的取对象。 k% W# p3 m5 u( s4 n6 m# G: Y() 函数调用运算符(Function-Call operator) 2 p4 W' P; x y- K0 C:: 范围解析运算符(Scope-Resolution operator): M0 e" P7 H6 d
如何定义一个指针变量 + z; ]! Z% f8 R5 G4 p, F* j' _假设类型T, 变量名称name, 指针的定义如下: . E) E( ?" m- l . w5 \; V$ B! HT* name;; E% U0 ^1 P; M W1 M" D+ X
标识变量名字name, 它是T类型的指针。例如 ' Z3 [2 s) ?' @( D/ s1 l3 s5 H q* t* K
int n = 0;+ T% \5 B( m& Z; i
int* p_n = &n;' x6 H# k# p' V* N/ q j
p_n是int指针类型, 指向某个int型的对象。 9 Q6 y, l {7 [( c6 B7 y1 U5 h h W7 R' F: z$ M" h9 c
指针变量的修饰* J- E1 E! x) b7 A. L% L
指针实际上也是一种变量类型, 只是它保存的内容有些特别, 是指定类型的地址值,通过间接寻址运算符(indirection operator)*, 可以访问到指针指向地址上的指定类型。2 B0 r7 A( f$ f+ g+ K. i
, h+ }/ t% D$ c* V
指针也可以用const, volatile修饰。 const int或int const均表示一个变量类型是int, 且该变量不能修改。以下两种写法都可以: ! k! [1 `/ @- T# |& J # `( S# Z9 l" aconst int a = 1; ' t2 o- V: H! x6 b$ m5 \9 _7 Q/ V& w( Lint const b = 2; ) r& {& C: X1 v1 C既然指针是也一种变量类型,同样支持被const修饰, 表示指针的值/指针的指向不允许修改, 指针所指向的那个变量是否允许修改, 那是另外修饰。写法如下: 7 u$ y+ R' Y r ?6 `) l . V: T5 c2 }- }' Aint a = 1; & q7 C! Q' R5 c" Jint b = 2;3 ?% r( L, B9 y/ p8 B- m( i9 @
int* const cp_a = &a; // 指针的修饰词,放在*号后面。: l! }0 q+ N* @. l& l- Q5 f/ }0 t4 \3 Y
*cp_a = 10; // 指针指向的值可以修改- \. D u/ E* \! Z; u3 J" s
cp_a = &b; // 指针不能被修改,报错! - {; A- ?' ^- ~9 v: ^7 H' n+ n总结带修饰的指针的格式:- h4 I+ ~+ C3 @0 C, l
只要记住修饰词总是放在被修饰的内容后面。 7 _# G! ]" n" I0 g( C 6 ^) j1 G3 ?6 ?2 ycv表示const / volatile修饰词。指针定义形式如下: 0 H: j* R- F- {9 g, d- @$ r& r9 Y4 V/ e: r
T [cv for T] * [cv for pointer] name. J% K1 J ~6 P
注意对T的修饰放在T的前面也是合法的写法。8 x* v& U' A7 L Q/ ?5 ?
6 J' Q/ f% p/ D# n- W Yconst int const c = 2; % X6 q+ m2 x! n- W在mscv编译器下也不会报错。 - Y; P/ }1 M, J- h3 r2 h- s: O, e& ]) u' V% n
完整的格式:0 ]: s$ D( q3 d$ Z
[cv for T] T [cv for T] * [cv for pointer] name 6 k6 G$ D ^# C4 U1 _# O0 c4 l! y. I8 H
Syntax meaning4 M9 d4 a! l, _+ s
const T* : s5 I% o$ r: b8 U$ Apointer to constant object- m8 O' N1 } A) G+ F8 r
) i( E4 i. K* t* h9 lint a[10];" [% {6 [5 S2 Q; F7 g) t1 W
int(*p_ary)[10] = &a; // p_ary是一个指针, 指向"int (*)[10]"类型的数组2 h5 H9 e# N& A X, S- ?- u
for (int i = 0; i < 10; i++) { * `$ {" O# l$ x9 @. h3 | // p_ary是一个指向数组的指针, 需要先通过间接寻址运算符*(indirection operator)取得数组对象- y. u0 t. Y2 {
// 再通过下标操作访问元素。 . l" C1 |2 s w. m1 S9 v3 b (*p_ary) = i; ( n, f0 G+ I; q; d+ v; T
} * \( O% R' k( r( V- V, d ) J9 R' |' P- N, K2 z; I8 Cint b[10];+ r- A8 k# v% w. O% t; P
int c[20];* O4 M) F9 Q& f% [
p_ary = &b; // 合法0 t* Z$ |* M$ R3 B
p_ary = &c; // 报错! 不能将 "int (*)[20]" 类型的值分配到 "int (*)[10]" 类型的实体 2 J( v4 f1 ~6 d, l$ o数组指针指向多维数组的子数组% b* r' j( ?. u7 q! H! n; V5 F
int a[10]; 7 p" N- i+ Q( N3 o: p4 Aint b[4][10];9 g: W: l# @ Y, |
int(*p_ary)[10] = &a; 5 Z3 m' G7 N! O& L$ D0 }for (int i = 0; i < 10; i++) { ! }3 E6 y" t' X1 o8 g (*p_ary) = 1; 1 f2 A, R6 ~. e! y! M& Q3 D, L0 l}! I5 I: E5 q0 D. x* O1 U9 }
$ w! q6 \+ ~7 r
p_ary = &b[2]; // 多维数组,可以看作数组的数组, 3 v% l2 K, Y# X# b7 T// b[2][0] ~ b[2][9]的值都被改成2了; B1 B+ n% B1 K0 }+ V1 i/ S
for (int i = 0; i < 10; i++) { 3 X+ d5 O4 O. G/ b3 ]- E7 J7 E (*p_ary) = 2;, I# o# P+ o; {( H; S3 g y
}9 S/ V4 e! O* n* K+ E& k' J
多维数组指针1 b! y$ i8 U/ x* z0 K/ E. |
多维数组指针,是一种指针,指向的对象是个多维数组,支持多个下标操作。 + L8 p* ?( x' k* j' q6 a ; [( v h7 g) gint a[2][5][10]; - ]6 g5 N# l4 c9 f* Mint(*p_ary1)[10] = &a[1][2]; // 1维数组指针- [) ^6 n' |' ^& ]0 C& V; j1 y- N
int(*p_ary2)[5][10] = &a[1]; // 2维数组指针1 J4 m! Z* |( e) i' ^5 j
for (int row = 0; row < 5; row++) { 1 ]1 o, Q" V$ \# G) w. I! K$ @& p for (int col = 0; col < 10; col++) { * e s: k! ?# z e" a; Y( z: Q; O: e (*p_ary2)[row][col] = row * col;: j J+ }; f$ D; Z. v. B
}: J& L4 \5 _( K3 }* z" F! ^+ q
} 6 ^. _& d) @7 F$ f& N$ t数组指针和指针数组对比实例5 _. M5 c" m# t4 A$ f6 \
数组指针还是记住两步法即可 9 }# B3 D, ?: k : U* t) C) T" C. }: W定义一个数组 7 J$ B) W* f3 A- l括号包围1中定义的名称,再在名称前加个*号。 ( c; J0 q7 v& m, `; f1 `int a[10];( E+ k6 T1 I# D f/ k! W
int(*ary_pointer1)[10] = &a; // 数组指针 % A3 c. y6 ^5 s7 x: e5 oint* pointer_ary1[10]; // 指针数组。元素类型是int*& J& P E7 C& L; ]" b
int *(ponter_ary2[10]); // 指针数组。另外一种定义方式。$ y# {! @4 j0 }$ C1 V' g
int (*ponter_ary3[10]); // 指针数组。另外一种定义方式。2 h# s! b* @+ z$ ] ]& K Q; L
int c, *d, (*ary_pointer2)[10], *pointer_ary3[10]; // 排列定义比较。+ k# n. {) q( N/ Z
! x& w9 X: H* b" Y0 ^, y7 ~
// 指针数组可以把每个元素指向数组对应位置的地址。 v8 k' r. I, H, G% T# h
// 这样遍历指针数组, 可以达到遍历数组元素的效果,但是注意每个元素都是指针, ! d! @; |) |7 i( o6 K0 [// 需要访问原数组的值的话, 需要对指针用*间接寻址运算符。 " A2 I# R& J* Y- j/ R% Kint* pointer_ary[10]; : B3 k5 _- V9 z/ l. q
for (int i = 0; i < 10; i++) { % U5 Q' D" Y) X+ {) V pointer_ary = &a; % y3 c, R5 B. c2 Y$ \} % v$ y' b- m0 r6 O+ Y$ V// 类似遍历原数组效果。% E" }1 N* j; k5 u$ o6 k
for (int i = 0; i < 10; i++) { + O; V4 D1 i; h3 c2 w6 p *pointer_ary = i; // 修改原数组。 9 O8 W( a+ q3 i" ]4 f2 T} 1 \8 T- g4 T' `& j L* `8 E1 x; n ) { t. I6 C) S2 G' V/ ~: w函数指针! D9 Q: i* E1 P7 x
取得函数地址 ; S$ b" M! @5 X3 g3 N函数的名称作为参数被传递时,会隐式转换成函数指针, 和在函数名称前加取地址符&等价。建议带上更加统一和清晰。2 ^5 E" Y5 e% p4 }
+ @. [- T; y* {) l" P
void f(int);. V( z; ]% ~& ~- M! W
int main() 6 a; D( m' }9 ^0 L1 L3 c{ / n/ d7 m1 x1 H6 M6 M void (*p1)(int) = &f;, p1 Q* N% b: t0 t! g
void (*p2)(int) = f; // same as &f% Q; T7 S. ?" E. y. @' t+ k
return 0; 1 b/ O1 v C" j. A) U) x" v} 5 y, L0 j6 y* j6 m8 h/ J翻译成汇编代码, p1和p2的赋值是一样的。8 ]; v/ E/ V0 c2 ~! j7 S9 r
- }) }/ H5 z* D0 a: P0 L% t , _, g3 d1 J" ~' ?& H9 N( e9 I) D% z/ M7 C+ p. q: S
函数指针的声明* M: D" ?; b# o- I* n
单个函数指针变量定义步骤8 h4 W0 I9 F. I8 L4 v
定义一个函数。void fun1(int a, int b); int fun2(double a); ! B6 v% {, H: s/ S. A用括号把函数名称包围起来,然后在名称前面加*号。void (*fun1)(int a, int b); int (*fun2)(double a);; t9 T D6 D, ~1 y# k
如果要定义函数指针数组,在定义单个函数指针的基础上,在名称后面加上[数组长度]void (*fun1[2])(int a, int b); int (*fun2[10])(double a); 7 C$ {) X) o$ {# Stypedef定义函数指针0 ]. a; H5 o$ f& R5 m+ r! K: S( ?
可读性高比单个定义要高,特别是声明多个同类型的函数指针,或者函数指针数组。6 M0 A2 v+ T. U! w, ]# W
. s/ ?# Y9 l: ?2 Ktypedef定义函数指针的语法 # B$ \# R0 _" s% _8 C. N/ M1 d1 q4 rtypedef有两种做法, 一种就是定义一种函数对象,另外一种就是定义函数指针。用法稍稍不同,效果是一样。其中函数对象不支持赋值, 但是支持引用。 , `4 O5 a# t1 x6 B: V. x 9 ^9 V6 |( h3 J) f' `, [typedef int FuncObject(int a, int b); // FuncObject类型是函数对象 9 T& s" W- h4 G1 O7 Stypedef int (*FuncPointer)(int a, int b); // FuncPointer类型是函数指针! L2 v7 K7 o% v
FuncObject* f1 = &Add; T7 O5 M1 Y: z- R+ XFuncPointer f2;) Y4 @% B5 p* m) A8 t0 d
f2 = f1; // f1, f2类型一样, 都是形式为int(int, int)的函数的指针。 5 H- c! _- F1 UFuncObject f3 = Add; // 报错! 函数对象不支持拷贝 $ s- L: e( i2 J4 wFuncObject f4 = &Add; // 报错!&Add是函数指针,与函数对象类型不匹配 7 _8 f% ?+ H4 B6 J4 `FuncObject& f5 = Add; // 正确1 e: J0 g* ~! K9 Q; r! t1 Z
int ret = f5(2, 3); // 正确9 g( O1 [3 t0 q7 |8 K, T$ Z
FuncObject& f6 = &Add; // 报错!&Add是函数指针,与函数对象引用类型不匹配 / T5 ^. \4 J8 ~! r# A! s* l如何记住typedef定义函数指针的步骤4 y' @+ t5 e3 K8 I
像定义一个函数指针那样, 指定一个名称。int (*CalFun)(int a, int b);, }1 E' _* T( b- l3 e! _% y' J0 u
在这个函数指针变量声明前面加上typedef。typedef int (*CalFun)(int a, int b);/ q2 u5 P# O6 L7 w, Z
完整例子 / n3 D8 G5 A/ n; z, gtypedef int(*CalFun)(int a, int b); 9 n+ a5 x3 a8 }. F \# r) n7 L# j9 c5 \+ f
int Add(int a, int b)1 z& W/ D' F: [! g0 Z, `( F" k
{ $ R& S) ]" I) s3 _5 t return (a + b); N1 |6 t( h' |: l& a& e8 {1 K0 d}; m* I* L+ l A2 ^3 I
4 p3 n% `6 `4 e& w2 Jint Sub(int a, int b) / P+ E: n7 C, b: Z" ~{ " D1 {0 D$ {( |# O8 @ return (a - b); . ^" L/ ]! k$ b6 e% }2 }3 T" U}1 T" j$ X, V& w1 d" m4 _
. j; a& E( r6 i: F% o/ K! c( g
int main(int argc, char** argv); }2 J- g$ J. |- Q' `! F, k: l
{ 6 E# Q* t6 Q/ y s' k% z* { CalFun f1 = Add; 1 ?/ _ d: ~$ l* \$ _+ f$ l4 V CalFun f2 = Sub; & G! R. W, ^! A, W int a = f1(2, 3);7 Y ]( o8 k2 Z* O
int b = f2(10, 5);. Q' Q+ f1 X' X! X9 A9 W* E* v
3 e5 n& w- W; S- d; g // typedef定义的函数指针数组。4 P. h; u& s0 r( y* E/ j
CalFun f_ary[2]; : Z7 C# A e! Y f_ary[0] = Add;3 k( N2 B6 C1 E7 c( I' t
f_ary[1] = Sub; 0 s3 u3 ~$ {. y; F; V6 g# L. }# w! j9 T0 L) n" D+ F/ g, {* V
// 单个定义的函数指针数组。) j2 \1 h1 S" ]; J
int(*f_ary2[2])(int a, int b);" F% M& I9 O9 W& f
f_ary2[0] = Add;# k* V/ f' X6 U( V/ `, w
f_ary2[1] = Sub;7 Y: N/ S5 t% o. x) Z* {
. ?- A! Q. ]+ i5 T return 0;/ T) m9 E/ ~0 F0 `; n' y
}' M8 L9 K: y! Z' b# Q
7 H+ E$ l- ~9 O1 M7 ~* a
using别名定义函数指针$ S4 A# d7 K! r3 O& M
c++11以后的类型别名定义--using也可以用于定义函数指针, typedef的好处它都有,个人感觉比typedef更直观。using类型别名同样分函数对象和函数指针两种方式。' R5 `4 X/ N! Q7 }
. N) `8 J% c* I$ R) Z; q
typedef int FuncObject(int a, int b); // FuncObject类型是函数对象 8 ?& u/ z5 v$ Q+ |using FuncObject = int(int a, int b); * H1 o1 `. N, Z7 x' Btypedef int (*FuncPointer)(int a, int b); // FuncPointer类型是函数指针 ' P) M2 p; N* r5 G9 }7 qusing FuncPointer = int(*)(int a, int b); 6 y C% ]. `* }: U, U# r2 j函数指针的调用 + ?& B2 C1 ~0 a0 h函数指针和函数对象都可以直接后加括号调用 + l4 C1 v3 H9 N: x1 ]- H5 O/ }- y9 Cint f(); 0 F. U& Q. O/ h# U9 Hint (*p)() = f; // pointer p is pointing to f 6 O5 c+ y9 d. q5 D9 @8 J/ ^/ @/ Vint (&r)() = *p; // the lvalue that identifies f is bound to a reference0 W- M. S( g& s- w0 P; x+ G
r(); // function f invoked through lvalue reference 8 X. \& n& d7 p# a: L(*p)(); // function f invoked through the function lvalue/ E+ d) d0 [- l' J b- B# M, Z# J3 b
p(); // function f invoked directly through the pointer 2 M E" o, C& U4 I3 E3 @' j1 y如果函数有重载, 函数指针会指向匹配的那个版本。 ! l: X2 J; O- N0 `) Gtemplate<typename T> 4 C) H( \! {+ FT f(T n) { return n; }- E0 T, _* a3 ^0 ]- \7 r
5 s0 j0 M" T8 G/ pdouble f(double n) { return n; } ) C5 N9 [+ @: g2 f4 `3 R 2 l6 ]3 L# Y; D* o. _int main(), t. [8 q, v- a3 @1 b j
{6 N* v& \1 U$ x/ z
int (*p)(int) = f; // instantiates and selects f<int>/ o: {5 [, _( l5 A* G6 k/ u3 h
} ! p! F6 V" a3 m% g4 i3 v. D成员函数指针7 j* r1 `/ Z* o4 n
静态成员函数,除了增加了访问控制以外,跟普通的函数指针没什么区别,所以普通函数指针可以直接指向类的静态成员函数。但非静态的成员函数与普通函数指针不太一样,声明时需要指定函数归属的类名,并且调用需要指定对象实例。 ; O* c H) n8 E8 Y2 U; W, k9 w ^7 v0 Z' v% f! b' Z成员函数指针定义。 . Z) R* L2 \: s2 u8 B/ y像定义类成员函数实现那样写, 并任意指定名称,这里作func。void ClassName::func(int); 4 d) Y0 H2 K2 H( ~2 K4 Q5 g6 e8 O括号把类名、范围解析运算符::、名称包围起来。void (ClassName::func)(int); ; i% _+ w# @2 j! E/ g, w在名称的前面加个*号void (ClassName::*func)(int);) Q) Z1 D% ^. O4 G) o
成员函数也支持typedef和using的定义方式。typedef void(C::* MemberFunc)(int); using MemberFunc = void(C::*)(int);/ Y% `8 Q; I) M7 |7 S
成员函数指针如何调用。 / o# N. v" H5 B9 a7 c3 o$ T, {假设成员函数指针名字为func 9 X# r: h3 }3 K2 Q9 [# y" S0 } % R3 O, \. u- H; x* a svoid (ClassName::*func)(int);! Q1 p0 W* g8 N; H2 V
对象式调用。 5 _! t) W" q. I1 s+ RClassName c; // 被调用的对象 8 E: _2 C7 N9 \4 g成员函数指针名字当作正常函数那样写。. s1 G! P& F. Q0 x
c.func(3);% A3 g3 ?2 ?: ^) D& @9 S
成员函数指针是指针, func名称前面需加上间接寻址运算符*,变成函数对象。 ' v. x3 ?- M- }- }c.*func(3);( w- w/ y# n( Z: j" Q
最后用括号把调用对象、成员访问运算符.、间接寻址运算符*、和成员函数指针的名称包围起来。' P, b' t+ C) q7 o M
(c.*func)(3); 8 Y( ~$ d1 C$ a5 j为何要加上括号? 根据c++的优先级标准,取成员运算符. > 函数调用() > 间接引用符*。 *号优先级比函数调用要低, 成员函数指针还没取得对象就被调用了,自然报错。 另外 2 G' n6 r' ~* a+ k& V(c.(*func))(3);; D6 s+ a& v O G) G
这样的写法也不行。 .*和->*是整体作为一个运算符的,中间不能用括号隔开。! p- o1 s: E4 o( {. o3 l R
指针式调用1 ?: S8 ]* x" P
ClassName* p; // 被调用的对象的指针 3 f# `4 g' [, }' a成员函数指针名字当作正常函数那样写。 - x6 x. u& o2 E7 S) j$ q# dp->func(3); * m, E c( O) i K( A$ O* ^+ c0 Z成员函数指针是指针, func名称前面需加上间接寻址运算符*,变成函数对象。 0 P; p1 A- U$ T4 v: R! q/ |0 B& t; Zp->*func(3); 0 U- s- G8 t. H U最后用括号把调用对象、成员访问运算符->、间接寻址运算符*、和成员函数指针的名称包围起来。' b0 ?8 H# R. M
(p->*func)(3);" g# s2 I7 ~8 k1 B$ q
函数指针使用完整例子 ) f& b* J8 ^6 N8 D0 o) dstruct Cal 0 I: O4 I9 L4 K* _5 I{ 7 @: g0 y+ P- [! y7 [7 ~
int add(int a, int b); ' \: E) {+ E- M$ ~: N, q/ h3 z int sub(int a, int b);/ c0 L& a; B) L/ h9 z, y1 t# T
}; / V3 A0 Y& M5 M) @$ y . T# k/ F! Y5 e. Q: E* @ y( uint main()7 z* o" G' j' Z3 X7 s7 t8 p
{ " E7 t. {5 j1 {) h- ^( h int (Cal::*fun)(int, int) = &Cal::add; . R4 P+ G% H) E. a$ ~ M fun = &Cal::sub; 5 C- g1 N0 H m2 t i" W 9 s1 p- Y, K) C% K Cal* p_cal = new Cal();! a5 E/ I7 p6 K4 n1 V% [. E
int r1 = (p_cal->*fun)(2, 3);0 |, R2 N; S; @
delete p_cal;3 p9 ^$ U; ]; w6 K, f
, i8 _3 G5 i# o" c* s/ D6 R" W2 K; e Cal local_cal; , w& `1 R' M9 | z/ H- f6 E" \ int r2 = (local_cal.*fun)(8, 6);( Z% m/ r& c7 O. M# @
} : w6 Q' _2 V' W5 @6 p- k: C, N ! b/ q; c. G& V2 j& a, r成员变量指针 ' |; K: ?# |1 N成员变量指针比成员函数指针还要简单些,没有函数调用, 无需考虑函数调用和间接引用符*的优先级问题。1 F& d: o/ r( T2 O/ J3 M8 v
$ B y+ r' s. ]9 h- V
成员变量指针的定义/ |) F/ ^1 h! {6 [
假如以下结构体C。 ; I5 s: C& J3 j5 p1 O: r ( E3 b2 R$ {( ?5 vstruct C 7 R5 C8 b {6 G* K{ 4 \1 V1 Q# K& @& Z4 X/ f4 w8 r int m; + Y0 q, I l8 }};8 g: {; V( W( q9 N7 W
单个成员变量指针定义 , X8 n6 q9 f- Y- y' K
假设名称为p, 类似静态成员变量定义那样声明! k! `5 @, K/ t$ {; ~
int C::p;6 E7 H( K8 _2 G! U" R
在名称前面加上指针标识号* ! o. N4 k: v, Q! E3 B- ?* y/ cint C::*p;4 K6 ]6 M8 X+ G
typedef或using方式定义! q2 n6 x, e6 J' l5 U8 r6 I# d
typedef int C::*MemberPointer;1 Y1 ^! u4 x \$ q8 Z
using MemberPointer = int C::*; ' e: ?8 i/ L. Y: p成员变量指针的使用。, R& D. ]- B3 B& n
类似成员函数指针那样,直接使用指向成员的指针运算符:.* 和->*即可。 ) R1 B3 g) \# n* L% x! z4 j3 ]! B成员变量指针, 能让我们实现一些遍历成员的动态功能。 例如把一个类/结构体的多个同类型的成员变量放进一个容器里,然后遍历访问这些成员变量。0 S& M! x& v2 `$ v/ t; A5 j
^* F ~+ _0 R' |* B9 z9 [7 M
完整例子% O8 j9 Q2 v/ [
struct C { int m; };$ i2 N; h: m4 |. X
int main() ) f& K* ]# l' {- v" v{8 i* z [7 p1 ]2 W' K4 X# W5 y
int C::* p = &C::m; // pointer to data member m of class C7 w3 P. L0 W& b1 a
C c = {7}; 0 y5 ?* J D- N @: k9 _) i1 Q. b std::cout << c.*p << '\n'; // prints 7 5 W" [! `" A0 f0 |- E C* cp = &c;- }: H2 o- n! \& y. a
cp->m = 10; % \5 P9 x" R/ k, k std::cout << cp->*p << '\n'; // prints 105 Y5 b7 T6 @, D d" n4 \* ?
4 j+ C: |! z, I2 O. \$ t4 V0 }————————————————& o' \3 k. [# ]: T. y; W
版权声明:本文为CSDN博主「南风fahaxiki」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。$ i9 f5 P. b7 {7 X m, U$ g
原文链接:https://blog.csdn.net/m0_64407685/article/details/1267881156 z% }4 Z1 c$ `. ^