他小的有

C++一个类如果不提供任何接口,如何访问它的私有变量

这个是我第一次笔试的笔试问题,当初我也才大四啊,想破头脑也想不出来,网上也少有人讨论这个(肯定有的,难道是当初我搜索的方式不对:(?也可能是我不理解这个题目的意思没找到答案),只记得课本上就写着,public为公有,protected为受保护的,private为私有,哪懂得这么多。

后面在我的学习和试验当中,我觉得至少有三种方法来实现它。先看一下这样一个类:

//不提供任何接口的类
class A
{
public:
	A();

private:
	int n;
};

假设存在这样一个类,没有任何的接口,我们现在需要访问变量n,我们是如何做到的呢,首先为了能可有据可证实我们确实已经访问到的这个变量,我们首先将它的值初始化一下,仅是用来确定我们是否能真正的访问到而已,如下:

//不提供任何接口的类
class A
{
	//这里给私有变量附值,仅用于判断是否真正能读取出而已
public:
	A()
	{
		n = 10;
	}

private:
	int n;
};

好了,我们现在已经给没有提供任何接口的类附了初始值,现在如果我们能读出赋给类的变量的初始值,就意味着这个问题我们解决了,看如下代码:

blob.png

通过上图可以知道,类A里面的n已经被初始化为10。现在我们可以通过地址去看一下pA所在的地址内存区域的内容,(在调试模式)按下ALT+5即可打开内存查看器。

blob.png

可以看到,在内存地址中0x00175AF8中的第一个字节为0a,我们知道一个int占用四个字节,所有0a 00 00 00其实就是代码int n = 10,在内存中的分部情况,那为什么不是00 00 00 0a呢,这个小涉及到大端小端的问题,之后我们再说,总之我们知道,内存中存在一个十进制为10的数,而且地址正好是类A实例的首地址。

分析完内存之后,我们就可以用程序来描述并将值读取出来了,看如下代码:

blob.png

首先我们先将pA的地址转为(void *),为什么不直接转为(int *)呢,这个敲下代码你可以试一试就知道了,这里卖个关,然后再转为(int *),再用(*)取得当前(int *)的值,所以n便等于10,这样就可以了回答了这个问题。

你以为这样就结束了?还没有,难道这个时候你没有任何疑问吗?为什么pA指针指向的内存区域就是class A中的成员变量n的值呢?如果该类中存在其它成员变量,那又会是怎么样的内存分布呢?如果该类中存在成员函数,那指向的首地址还会是这个首个成员变量的地址吗?如果存在虚函数还会是吗?如果是为什么,不是又是什么原因不是了呢?——《深度探索C++对象模式》这本书非常合适你!

当然这里还要提一句就是,可能受到字节对齐的问题,你看到的内存内容并非完全是你认为的每个类型占用的内存大小,这个你可以试一试三个变量,分别是int ,char, double型,然后按照刚才的方法查看内存区域的内容你就明白了,字节对齐的这个问题我们之后再详说。


除了上面的这种方式外,还有两种其它的方式。

一种是内存拷贝,其实原理和上面的一样,什么意思呢?比如我再做一个class B,成员和class A一样,但是设为公有的,然后将A的实例化的地址附到B,或者拷贝到B中去,就达到了B的实例的内容正好等于A实例的内容,像上面这样访问class B中的public n就好可以了。

另外一种是友员类,到友员类的时候再详谈,当然如果这个类之前就已经被封装好不能动代码的情况下,这个自然就用不了,所以也就是为什么一开始我就强调它没有任何的限制的原因。

如果你有更多或更好的方案,期待你的留言!

本站部分资源收集于网络,纯个人收藏,无商业用途,如有侵权请及时告知!

0
分享到:

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址