指向类成员的指针
C++扩展了指针在类中的使用,使其可以指向类成员(数据成员和函数成员),这种
行为是类层面的,而不是对象层面的。
#include <iostream>
using namespace std;
class A
{
public:
int x;
void foo()
{
cout<<x<<endl;
}
};
int main()
{
A a;
A *p = &a;
p->foo();
return 0;
}
指向非静态数据成员的指针在定义时必须和类相关联,在使用时必须和具体的对象
关联。
由于类不是运行时存在的对象。因此,在使用这类指针时,需要首先指定类的一个
对象,然后,通过对象来引用指针所指向的成员。
声明
<数据类型><类名>::*<指针名>
初始化
<数据类型><类名>::*<指针名> [=& <类名>::<非静态数据成员>]
解引用
<类对象名>.*<指向非静态数据成员的指针>
<类对象指针>->*<指向非静态数据成员的指针>
#include <iostream>
using namespace std;
class Student
{
public:
Student(string n, int nu):name(n),num(nu){}
string name;
int num;
};
int main()
{
Student s("zhangsan",23);
Student s2("lisi",25);
// string *ps = &s.name;// 跟封装相违背
// cout<<*ps<<endl;
string Student::*pn = &Student::name;
// 通过对象访问成员变量
cout<<s.*pn<<endl;// 输出s对象的name成员变量的值
cout<<s2.*pn<<endl;// 输出s2对象的name成员变量的值
//创建一个指向Student对象的指针
Student *ps = new Student("zhaoliu",35);//动态创建一个名为"zhaoliu",编号为35的学生
// 通过指针访问成员变量
cout << ps->*pn << endl; // 输出ps指向对象的name成员变量的值
// 释放动态分配的内存
delete ps;
return 0;
}
指向类成员的指针,具有指针的形而不具体指针的实,或者,确切意义上说,不指
是指针。
指向类成员的指针,本质存放的不是地址,存放的偏移量。
指向 函数 成员的指针
定义一个指向非静态成员函数的指针必须在三个方面与其指向的成员函数保持一
致:参数列表要相同、返回类型要相同、所属的类型要相同。
由于类不是运行时存在的对象。因此,在使用这类指针时,需要首先指定类的一个
对象,然后,通过对象来引用指针所指向的成员。
声明
<数据类型>(<类名>::*<指针名>)(<参数列表>)
初始化
<数据类型>(<类名>::*<指针名>)(<参数列表>)[=&<类名>::<非静态成员函数>]
解引用
(<类对象名>.*<指向非静态成员函数的指针>)(<参数列表>)
(<类对象指针>->*<指向非静态成员函数的指针>)(<参数列表>)
#include <iostream>
using namespace std;
// 定义一个结构体Point
struct Point
{
// 成员函数,用于加法运算
int plus(double x, double y) {
return x + y;
}
// 成员函数,用于减法运算
int minus(double x, double y) {
return x - y;
}
// 成员函数,用于乘法运算
int mul(double x, double y) {
return x * y;
}
// 成员函数,用于除法运算
int div(double x, double y) {
return x / y;
}
};
// 定义一个函数oper,用于执行Point结构体的成员函数
int oper(Point & point,
int (Point::* pfun)(double x, double y), // 指向Point结构体成员函数的指针
double x,
double y
)
{
// 通过对象和成员函数指针调用成员函数
return (point.*pfun)(x, y);
}
int main()
{
// 创建一个Point对象
Point pt;
// 定义一个指向Point结构体成员函数的指针
int (Point::* pfun)(double, double);
// 将pfun指向Point::plus成员函数
pfun = &Point::plus;
// 通过oper函数调用Point::plus成员函数,并输出结果
cout << oper(pt, pfun, 10, 20) << endl; // 输出30
// 将pfun指向Point::minus成员函数
pfun = &Point::minus;
// 通过oper函数调用Point::minus成员函数,并输出结果
cout << oper(pt, pfun, 10, 20) << endl; // 输出-10
return 0;
}
指向 函数 成员的指针 更加隐蔽的接口
#include <iostream>
using namespace std;
// 定义一个名为Widget的类
class Widget
{
public:
// 构造函数,初始化成员函数指针数组
Widget()
{
pf[0] = &Widget::f; // 将成员函数f的地址赋值给pf[0]
pf[1] = &Widget::g; // 将成员函数g的地址赋值给pf[1]
pf[2] = &Widget::h; // 将成员函数h的地址赋值给pf[2]
pf[3] = &Widget::i; // 将成员函数i的地址赋值给pf[3]
}
// 获取计数器cnt的值
int getCount()
{
return cnt;
}
// 根据输入的sec值选择调用不同的成员函数
void select(int val, int sec)
{
// 检查sec值是否在有效范围内
if(sec < 0 || sec > 3) return;
// 使用成员函数指针调用对应的成员函数
(this->*pf[sec])(val);
}
private:
// 定义四个私有成员函数
void f(int val) { cout << "void f()" << val << endl; }
void g(int val) { cout << "void g()" << val << endl; }
void h(int val) { cout << "void h()" << val << endl; }
void i(int val) { cout << "void i()" << val << endl; }
// 定义一个枚举常量cnt,值为4
enum { cnt = 4 };
// 定义一个成员函数指针数组,数组大小为cnt
void (Widget::*pf[cnt])(int);
};
int main()
{
// 创建一个Widget对象
Widget w;
// 调用select方法,传入参数100和2,将调用成员函数h
w.select(100, 2);
return 0;
}
指向静态成员的指针
指向静态成员的指针的定义和使用与普通指针相同,在定义时无须和类相关联,在使用时也无须和具体的对象相关联。
声明
<数据类型>*<指针名>
初始化
<数据类型>*<指针名>[=& <类名>::<静态数据成员>]
解引用
(*<指向静态数据成员的指针>)
声明
<数据类型>(*<指针名>)(<参数列表>)
初始化
<数据类型>(*<指针名>)(<参数列表>)[=&<类名>::<静态成员函数>]
解引用
(*<指向静态成员函数的指针>)(<参数列表>)
#include <iostream>
using namespace std;
// 定义一个类A
class A
{
public:
// 声明一个静态成员函数dis
static void dis();
// 声明一个静态成员变量data
static int data;
};
// 定义静态成员函数dis,输出静态成员变量data的值
void A::dis()
{
cout << data << endl;
}
// 定义静态成员变量data并初始化为100
int A::data = 100;
int main()
{
// 创建一个指向A类静态成员变量data的指针pa
int *pa = &A::data;
// 输出指针pa所指向的值,即data的值
cout << *pa << endl;
// 创建一个指向A类静态成员函数dis的函数指针pf
void (*pf)() = A::dis;
// 通过函数指针pf调用静态成员函数dis
pf();
return 0;
}