C++静态成员函数访问非静态成员的几种方法

来源:互联网 发布:阿里数据银行 编辑:程序博客网 时间:2024/06/05 13:06

大家都知道C++中类的成员函数默认都提供了this指针,在非静态成员函数中当你调用函数的时候,编译器都会“自动”帮你把这个this指针加到函数形参里去。当然在C++灵活性下面,类还具备了静态成员和静态函数,即

复制代码
class A{public:    static void test()    {        m_staticA += 1;    }private:    static int m_staticA;    int m_a};
复制代码

此时你的test函数只能去访问m_staticA成员,而不能去访问m_a。同学可能会问,这算什么问题?问题都是在应用场景中才能体现的,我一开始也是不以为意,直到我遇到了回调函数这个烦人的问题我才真正静下心来去考虑这个知识点。

先简单说下回调,在座的应该都知道回调的含义,在C中回调主要体现就是回调函数,当然C++中也有仿函数等其他用法,抛开这些,单纯在回调函数这个点上我们进行如下讨论。

由于C++类的成员函数都隐含了this指针,如果我直接注册,比如

typedef void (A::*FunPtr)();FunPtr p = A::hello;p();

此时程序会报错,提示信息是你缺少一个this指针,意味着你要真的想使用p,你必须有一个分配好空间的实例才能来调用

复制代码
typedef void (A::*FunPtr)();FunPtr p = A::hello;A a;A *pA = new A();(a.*p)();(pA->*p)();
复制代码

当然,如果仅仅是对C++的类静态函数进行回调函数注册,你是不需要考虑this指针的

typedef void (A::*FunPtr)();FunPtr p = A::test;p();

但问题就是,你此时的静态函数是不能拥有你的成员变量的,看到了吧,问题来了。面对这种需求,我们就真正应该静下心来好好想想,究竟如何才能让静态函数去访问非静态成员变量这个问题了。

方法一:

有一个很取巧的办法,就是在静态函数的形参表里加上实例的地址,也就是

复制代码
class A{public:    static void test(A *a)    {        a->m_a += 1;    }    void hello()    {    }private:    static int m_staticA;    int m_a};
复制代码

这样在你回调函数的时候,你可以通过这个来让本身不能访问成员非静态变量的静态函数(太拗口)来访问非静态成员变量。

方法二:

其实这个方法在GLIB中用的很多,就是放上全局变量地址即

复制代码
A g_a;class A{public:    static void test()    {        g_a.m_a += 1;    }    void hello()    {    }private:    static int m_staticA;    int m_a};
复制代码

这种方法我们了解就好,全局变量我们并不推荐。

方法三:

大家都知道静态成员函数不能访问非静态成员,但别忘了,他们可以访问静态成员,也就是说,如果我们的这个类是个单例,我们完全可以在创建的时候把this指针赋值给那个静态成员,然后在静态成员函数内部就可以放心大胆的使用了。

复制代码
class A{public:    A()    {        m_gA = this;    }    static void test()    {        m_gA.m_a += 1;    }    void hello()    {    }private:    static int m_staticA;    static A *m_gA;    int m_a};
复制代码

方法四:

和方法一比较像,但他的方向思想更多的是针对内存块这个概念,意思就是在静态函数的形参比加上一个void *的内存首地址,然后在内部做转换

复制代码
class A{public:    static void test(void *pData)    {        A *a = (A *)pData;        a->m_a += 1;    }    void hello()    {    }private:    static int m_staticA;    int m_a};A a;test(&a);
复制代码

如上,我整理了4种方法,当然方法还有很多,其实绕了这么大远路,我们的希望就是不破坏回调函数整洁的函数接口(加上自己的实例指针)而做的妥协,如果你更喜欢通过改变接口或者通过用Java类似的interface方式来实现,那也没有问题,这里主要就是提供给大家一个思路,C++确实很灵活,我们要用好这把双刃剑 : )

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红米1s进水后开机了黑屏了怎么办 魅族手机已锁定魅族账号忘了怎么办 魅族5糸统升级后开不了机了怎么办 如果别人用电脑登了你的微信怎么办 消逝的光芒买错了买的普通版怎么办 在人人车卖了个车买家不过户怎么办 应用锁密码和密保问题都忘了怎么办 不小心在微信公众号发了消息怎么办 微信漂流瓶不能用了被投诉了怎么办 货物少了拉货的不承认少了怎么办 寄的快递号码留错了已经寄走怎么办 网购快递放在单位门卫室丢了怎么办 顺丰生鲜速配时效内食物坏了怎么办 竟尤理财跑路怎么办钱追的回来吗 博贝游戏用支付宝提不了现该怎么办 陌陌钱包没绑支付宝就体现了怎么办 鞋子让太阳晒的一只大一只小怎么办 美团不让上饿了么平台们商家怎么办 在汇通信诚租贷款买车被骗后怎么办 我的网银账户里的钱被盗了怎么办 老赖跑到国外去了还换了国籍怎么办 内裤把屁股两边磨得又肿又疼怎么办 京东在面临供货商不供货时怎么办的 打错的消息想撤回但按了删除怎么办 顺丰快递寄的黄皮和荔枝坏了怎么办 我发快递写错地址备签收不还怎么办 新买的床上四件套用着全身痒怎么办 华为畅玩6x锁屏密码忘了怎么办 我在淘宝上买了货不发货咋怎么办 在快递公司寄的东西丢了我该怎么办 不小心给了快递员子一个差评怎么办 不小心用发霉了的杯子喝了水怎么办 唐三复活了小舞失去的魂环怎么办了 我该怎么办?身陷动漫城输了很多钱 庄家开2球大小球踢成2球怎么办 去哪儿网订机票时邮箱写错了怎么办 在南航航班上把手机丢飞机上怎么办 买了品牌鞋穿了一周就破了怎么办 狗让狠狠的打了一顿不理人了怎么办 调好米粉宝宝吃的时候就凉了怎么办 情人间闹分手删了微信后悔了怎么办