C++中的类成员指针
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文!
本博客全网唯一合法URL:http://www.cnblogs.com/acm-icpcer/p/6729273.html
C++中的类成员指针
在上一篇文章中我提到了C++中的函数指针。那么如果想定义一个指向类数据成员或者函数成员的指针,又该怎么办呢?
本质上讲和之前我提到的写法没有什么不同,只不过是要加上域定义而已。
1.类数据成员指针
例如,对于下面的类A:
class A { public: int x; int sayhello() { cout<<"hello world"<<endl; } };
假如我想定义一个指向数据成员x的指针,则:
int A::*pointer1 = &A::x;
很明显,去掉域定义其实就是普通的指针定义:int pointer1=&x;
那么,如果用typedef来简化语法就是:
typedef int A::*int_pointer;
int_pointer pointer2 = &A::x;
两者是等价的。
调用指针时则为:
A a; a.*pointer1 = 6; ++(a.*pointer2); cout << &a->*pointer1 << endl;
结果为7。(注意:必须声明一个A的对象才可以调用类数据成员指针)
那么这个类数据成员指针究竟是地址还是什么呢?
为了搞清楚,我们就把它打出来看看吧:
cout << pointer1 << endl << pointer2 << endl;
结果是1 1。
这是什么意思呢?实际上,类数据成员指针只是相对于对象在内存中初始地址的一个偏移量,也就是说,它是一个相对地址。
2.类函数成员指针
现在,我们讨论一下类函数成员指针的定义和使用。我们的讨论建立在以下类A和类B的基础上来讲:
class A { private: int y; public: double w; int x; int sayhello() { cout<<"hello world"<<endl; } }; class B:public A { };
类成员函数指针定义:
int (A::*classAfunctionpointer1)();
classAfunctionpointer1 = &A::sayhello;
可以看到,这其实也是在普通的全局函数指针前面加上了一个域定义而已(普通全局函数指针:int (*classAfunctionpointer1)();)。
那么,如果用typedef来简化语法就是:
typedef int (A::*FP)();
FP classAfunctionpointer2 = &A::sayhello;
调用时都是一样的:
(a.*classAfunctionpointer1)();
(a.*classAfunctionpointer2)();
或者
(&a->*classAfunctionpointer1)();
(&a->*classAfunctionpointer2)();
结果都是打印出hello world。(注意:类成员函数指针在使用前必须先声明一个对象)
那么,类B继承了类A,理论上讲B也可以使用A的指针:
B b;
(b.*classAfunctionpointer1)();
确实可以,结果也是打印出hello world。
那么这又是为什么呢?
实际上,类成员函数的地址是绝对的,因为类成员函数是定义在一个固定的代码区中。当年使用不同的对象去调用同一个类成员函数的时候,本质上,编译器会把该对象的this指针默认加在该成员函数的形参列表中,以便让函数明白是谁在调用它。所以不同的对象去调用同一个类成员函数的时候,编译器才能理解并作出反应。
3.示例代码
好了,根据上面讲到的所有基础知识,我给出如下程序:
#include<iostream> using namespace std; class A { private: int y; public: double w; int x; int sayhello() { cout<<"hello world"<<endl; } }; class B:public A { }; typedef int A::*int_pointer; typedef int (A::*FP)(); int main() { int A::*pointer1 = &A::x; int_pointer pointer2 = &A::x; A a; a.*pointer1 = 6; ++(a.*pointer2); cout << &a->*pointer1 << endl << pointer1 << endl << pointer2 << endl; double A::*pointer3 = &A::w; cout<<pointer3<<endl; B b; a.sayhello(); int (A::*classAfunctionpointer1)(); classAfunctionpointer1 = &A::sayhello; FP classAfunctionpointer2 = &A::sayhello; (a.*classAfunctionpointer1)(); (a.*classAfunctionpointer2)(); (&a->*classAfunctionpointer1)(); (b.*classAfunctionpointer1)(); return 0; }
TZ
2017/4/18于华中农业大学
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY