C++静态成员函数访问非静态成员的几种方法
大家都知道C++中类的成员函数默认都提供了this指针,在非静态成员函数中当你调用函数的时候,编译器都会“自动”帮你把这个this指针加到函数形参里去。当然在C++灵活性下面,类还具备了静态成员和静态函数,即
class A
{
public:
static void test()
{
m_staticA += ;
}
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 += ;
}
void hello()
{
}
private:
static int m_staticA;
int m_a
};
这样在你回调函数的时候,你可以通过这个来让本身不能访问成员非静态变量的静态函数(太拗口)来访问非静态成员变量。
方法二:
其实这个方法在GLIB中用的很多,就是放上全局变量地址即
A g_a; class A
{
public:
static void test()
{
g_a.m_a += ;
}
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 += ;
}
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 += ;
}
void hello()
{
}
private:
static int m_staticA;
int m_a
}; A a;
test(&a);
如上,我整理了4种方法,当然方法还有很多,其实绕了这么大远路,我们的希望就是不破坏回调函数整洁的函数接口(加上自己的实例指针)而做的妥协,如果你更喜欢通过改变接口或者通过用Java类似的interface方式来实现,那也没有问题,这里主要就是提供给大家一个思路,C++确实很灵活,我们要用好这把双刃剑 : )
C++静态成员函数访问非静态成员的几种方法的更多相关文章
- C++ 中静态成员函数访问非静态成员变量的方法
最近在 VS2010 里开发出厂烧写工具,遇到一个问题: 我创建了一个线程,在这个线程里要访问非静态成员,而这个线程函数是静态的.最后找到的办法是用对象指针来做. sourcecode: #test. ...
- 关于C++静态成员函数访问非静态成员变量的问题
静态成员函数不能访问非静态成员,这是因为静态函数属于类而不是属于整个对象,静态函数中的 member可能都没有分配内存.静态成员函数没有隐含的this自变量.所以,它就无法访问自己类的非静态成员 代码 ...
- PHP静态成员变量和非静态成员变量
数据成员可以分静态变量.非静态变量两种. 静态成员: 静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会 ...
- [C++基础]C++中静态成员函数如何访问非静态成员
#include <iostream> /* 静态成员函数只能访问静态数据成员.静态成员函数和类以外的函数和数据,不能访问非静态数据成员,但静态成员函数或静态数据成员可由任意访问许可的函数 ...
- 为什么c++中,有时可以用类名直接访问非静态成员函数?
正规的C++语言标准目前(截止到C++14)应该还不支持这种调用方法.目前微软似乎在它的VC++中推行一种叫做C++/CLI的标准,有可能会支持这种调用,如果一定要用这种调用方法的话,还应该用VS20 ...
- php取得当前访问url文件名的几种方法
php下获取当前访问的文件名的几种方法.推荐函数:一是PHP获取当前页面的网址: dedecms用的也是这个哦. <?php //获得当前的脚本网址 function GetCurUrl() { ...
- MFC控件编程之 按钮编辑框.静态文本的使用,以及访问控件的七种方法.
MFC控件编程之 按钮编辑框.静态文本的使用以及访问控件的七种方法. 一丶按钮.静态文本的通用属性. 他们都有一个属性.就是可以输入标题内容.以及可以自定义控件ID. 创建一个MFC Dlg对话框. ...
- struts2的action访问servlet API的三种方法
学IT技术,就是要学习... 今天无聊看看struts2,发现struts2的action访问servlet API的三种方法: 1.Struts2提供的ActionContext类 Object g ...
- Action访问Servlet API的三种方法
一.为什么要访问Servlet API ? Struts2的Action并未与Servlet API进行耦合,这是Struts2 的一个改良,从而方便了单独对Action进行测试.但是对于Web控制器 ...
随机推荐
- 普通用户从非80端口启动tomcat,通过端口转发监听80端口
linux下小于1024的端口都需要root去绑定. root权限启动tomcat是不明智的,可以使用非root权限启动tomcat监听8080端口,然后利用端口转发实现对80端口的监听. 端口转发: ...
- Get familiar with key Frameworks of ios
Frameworks make your life easier as an iOS Developer. They allow you to reuse code written by other ...
- Linux下常用I/O模型
Linux异步I/O是Linux内核中提供的一个相当新的增强.它是2.6版本内核的一个标准特性,异步非阻塞I/O背后的基本思想是允许进程发起很多I/O操作,而不用阻塞或等待任何操作完成.稍后或在接收到 ...
- hdoj 1789 Doing Homework again
Doing Homework again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- hdoj 1047 Integer Inquiry
Integer Inquiry Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- oracle10g前期准备
上午在虚拟机安装了oracle10g,安装比较简单,只是前期工作比较多,如: 在Root用户下执行以下步骤: 1)修改用户的SHELL的限制,修改/etc/security/limits.conf文件 ...
- MSSQLSERVER数据库- 打开表出现目录名无效
打开SQLSERVER数据库,出现目录名无效,如下图: 解决方法到 临时目录:C:\Documents and Settings\Administrator\Local Settings\Temp 手 ...
- jsp+urlrewrite实现html分页简单粗暴实现
今天去检查一同事写的一分页实现,看了有点郁闷,都说了要换成html实现方便搜索引擎收录,他还是用的js,真是晕.还得帮他解决 好吧.言归正传,我在他的基础上粗暴的修改了下,达到了基本的效果,带数字分页 ...
- chrome下老是弹出网页显示 true
事实上这个问题是chrome下安装了一些插件的原因,一般来说是安装迅雷插件会出现这个问题,删除迅雷插件就好了.
- oracle16 例外
例外处理 例外的分类 oracle将例外分为预定义例外,非预定义例外和自定义例外三种. 预定义例外用于处理常见的oracle错误 非预定义例外用于处理预定义例外不能处理的例外 自定义例外用于处理与or ...