如何理解int x:: *v[] = { &x::a,&x::b,&x::c };

如何理解“int x:: *v[] = { &x::a,&x::b,&x::c };”
以及func()方法的底层逻辑?

#include <iostream>
using namespace std;

class x
{
public:
    int a, b, c;
    x() { a = b = c = 0; };
    x(int i) { a = i; b = c = 0; };

};

int x:: *v[] = { &x::a,&x::b,&x::c };

void func(x *a, int x:: *b, int c) {

    a->*b = c;
}

int main() {

    x a(1), b(304);
    x *c = new x(-13);

    f(&a, v[0], 3);
    f(&b, v[1], 2);
    f(c, v[2], 1);
    cout << a.a << " " << b.b << "" << c->c;
    return 0;
}
#include <iostream>

using namespace std;

class x {
public:
  int a, b, c;
  x() { a = b = c = 0; };
  x(int i) {
    a = i;
    b = c = 0;
  };
};

// 下面语句的意思是,定义一个指向x类中int类型非静态数据成员的指针数组,并初始化。
// 指向非静态数据成员的指针,和其他类型指针不同,它不能强制转化成其他指针,
// 也不支持指针运算和解引用,它只能通过->*或.*运算符使用。
// 大多数编译器使用非静态数据成员在类/结构体中的偏移量来实现这类指针
// https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_members
int x::*v[] = {
    &x::a, // &x::a返回的是数据成员a在x中的偏移,结果是0
    &x::b, // &x::b返回的是数据成员b在x中的偏移,结果是4
    &x::c  // &x::c返回的是数据成员c在x中的偏移,结果是8
};

void func(x *a, int x::*b, int c) {
  // ->*和.*是指向成员指针访问运算符,下面语句等价于(*a).*b = c;
  // ->*左边必须是对象指针,.*左边必须是对象
  // 表达式a->*b运算的结果是,在a所指对象中b指针(偏移量)所指的数据成员
  // 底层实现就是通过对象基址a加上偏移量b获得数据成员实际地址,然后对这个地址上的数据成员赋值
  // https://en.cppreference.com/w/cpp/language/operator_member_access#Built-in_pointer-to-member_access_operators
  a->*b = c;
}

int main() {
  x a(1), b(304);
  x *c = new x(-13);

  func(&a, v[0], 3); // 等价于a.a = 3
  func(&b, v[1], 2); // 等价于b.b = 2
  func(c, v[2], 1);  // 等价于c.c = 1
  cout << a.a << " " << b.b << " " << c->c;  // 输出3 2 1
  return 0;
}

就是数组成员必须是A类的整型成员变量的指针。函数就是修改A类对象成员b进行赋值。这里是域,表明是静态的,就象函数指针一样。