C++ private访问限制

了解C++的同学都很清楚,C++有3个访问控制符,提供了对数据的封装,分别是public、protected与private。

private算是对数据保护得最严实的控制符了,一般都会说到private成员只能被类本身的成员函数以及类的友元访问,其他函数需要访问时,

大多数会封装一个public的set和get方法进行访问,或者 返回指针与引用也是可以的,但并不推荐,毕竟这样不利于封装的特性,

当然,下面介绍的方法是进行讨论使用其他方式突破private的访问限制,一般情况下也不会使用。

那么先从代码开始吧。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 class TestClass
 5 {
 6 public:
 7     TestClass() : m_nA(1), m_nB(2), m_nC(3) {};
 8     ~TestClass() {};
 9     void PrintValue()
10     {
11         cout << "m_nA: " << m_nA << "\t" << "m_nB: " << m_nB << "\t" << "m_nC: " 
12             << m_nC << endl;
13     }
14 private:
15     int m_nA;
16     int m_nB;
17     int m_nC;
18 };
19 int main()
20 {
21     TestClass Test;
22     Test.PrintValue();
23 
24     cout << "---------------------------------------------------" << endl;
25     
26     int nValue = 7;
27     int* ptr = (int*)(&Test);
28     *(ptr++) = nValue++;
29     *(ptr++) = nValue++;
30     *(ptr++) = nValue++;
31 
32     Test.PrintValue();
33 
34     return 0;
35 }

 

当声明了一个Test对像时,那么系统将会开辟一段连续的空间,此对象将会有如下的内存布局,如何正确的访问,需要考虑到字节的对齐。

 

 

 

 有了内存空间,当然可以使用指针进行访问,那么强行对此内存地址赋值即可。

27~30行的操作就是如此。

简单的总结来说,访问说明信息通常是在编译期间消失,在程序运行期间,对象变成了一个存储区域,别无他物,

因此,如果有人想破坏这些规则并且直接访问内存中的数据,是很容易的(存在大量的数据,继承时,使用此方法精确的更改数据内容就会变得非常困难),

C++并不能防止这种不明智的操作,毕竟C++关注的焦点是抽象。

 

那么除此之外还有其他方法吗?

答案是有的

比如声明另一个classB,只需要在classB中,把classA的private的访问控制符更改为public。

此时,相应的对象B与对象A的内存布局是一致的,只是访问限制不同,所以可以利用访问对象B的规则去访问对象A。

一个指向B对象的指针实际指向了一个A对象,对B中public成员变量的访问实际上是对A对象中private成员变量的访问。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 class TestClass
 5 {
 6 public:
 7     TestClass() : m_nA(1), m_nB(2), m_nC(3) {};
 8     ~TestClass() {};
 9     void PrintValue()
10     {
11         cout << "m_nA: " << m_nA << "\t" << "m_nB: " << m_nB << "\t" << "m_nC: " 
12             << m_nC << endl;
13     }
14 private:
15     int m_nA;
16     int m_nB;
17     int m_nC;
18 };
19 
20 class TestClassB
21 {
22 public:
23     TestClassB() : m_nA(11), m_nB(22), m_nC(33) {};
24     ~TestClassB() {};
25     void PrintValue()
26     {
27         cout << "m_nA: " << m_nA << "\t" << "m_nB: " << m_nB << "\t" << "m_nC: "
28             << m_nC << endl;
29     }
30 public:
31     int m_nA;
32     int m_nB;
33     int m_nC;
34 };
35 
36 int main()
37 {
38     TestClass a;
39     TestClassB* b = (TestClassB*)&a;
40     a.PrintValue();
41     b->m_nA = 6;
42     b->m_nB = 9;
43     cout << "m_nA:" << b->m_nA << endl;
44     cout << "m_nB:" << b->m_nB << endl;
45     a.PrintValue();
46     return 0;
47 }

 

posted @ 2020-05-18 19:52  大梦无痕  阅读(1045)  评论(0编辑  收藏  举报