成员指针
首先感谢知乎大大为我指点迷津
https://www.zhihu.com/question/51441745?from=profile_question_card
一、注意成员指针不是指针
引用大大的话,成员指针是:
在一个对象内部定位某一个成员的方式
首先我尝试输出成员指针的值:
class A
{
public:
int x;
int y;
};
int main()
{
int A::*p = &A::x;
A a = {20,30};
cout << a.*p << endl;//输出20
cout << p << endl;//1
p = &A::y;
cout << p << endl;//1
p = 0;
cout << p << endl;//0
}
….你是bool变量吗,之后我通过下断点在编译器里看到了它的值
int main()
{
int A::*p = &A::x;
A a = {20,30};
cout << p << endl;//&A::x
p = &A::y;
cout << p << endl;//&A::y
p = 0;
cout << p << endl;//NULL
}
可以,不知道它具体的值是多少,反正不是个指针
一些愚蠢的尝试(接上文)
p = &A::x
void *pp = *(int**)&p;
cout << pp << endl;//0
void *pp = *(void**)&p;
cout << pp << endl;//0
二、基本功能
之后的代码都是用的类A
int A::*p = &A::x;
A a = {20,30};
cout << a.*p << endl;//20
a.*p = 100;//等同于 a.x = 100
cout << a.*p << endl;//100
A *aa = &a;
cout << aa->*p << endl;//100
aa->*p = 200;//等同于 a->x = 200
cout << aa->*p << endl;//200
三、父子类的情况
增加一子类B
class B:public A
{
public:
int z;
};
int A::*p = &A::x;
int B::*q = &B::x;
A a = {20,30};
B b;
b.x = 21;
b.y = 31;
cout << a.*p << endl;//20
cout << b.*p << endl;//21
cout << a.*q << endl;//error
cout << b.*q << endl;//21
p = &B::x;//可行且值仍为&A::x
p = &B::z;//无法将‘int B::*’转为‘int A::*’
q = &A::x;//可行且值为&A::x
可预知的,无法在父类中使用子类的成员指针,毕竟子类会比父类多一些成员。
此外,我们发现只要是指向父类成员的指针,其值一直为”int A::*?”,在上述例子中无论对q,p怎样赋值,只要其指向x,y时,就只会出现值“&A::x”,“&A::y“。
四、成员函数指针
对类A进行修改
class A
{
public:
int x;
int y;
void fun(){cout << "A.x:" << x <<endl;}
};
void (A::*pFun)() = &A::fun;
A a = {12,13};
(a.*pFun)();//A.x:12
成员函数指针的其他情况大多与成员指针一致。注意,不可调用构造和析构函数。
此外,面对参数太多,太过复杂的函数,我们可以寻求auto的帮助(太棒啦):
auto pp = &A::fun;
(a.*pp)();//A.x:12
五、与模板的互动
template<typename T>
class IsClass
{
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C>
static One test(int C::*) {}
template<typename C>
static Two test(...) {}
public:
enum { Yes = sizeof(test<T>(0)) == 1 };
};
int main()
{
IsClass<int> m;
cout << m.Yes << endl;
IsClass<A> n;
cout << n.Yes << endl;
return 0;
}
如果类型T是一个类,那么0就会匹配”int C::*”类型,以此区分一个类型是不是一个类。