﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-iwong</title><link>http://www.cppblog.com/iwong/</link><description /><language>zh-cn</language><lastBuildDate>Thu, 09 Apr 2026 01:39:52 GMT</lastBuildDate><pubDate>Thu, 09 Apr 2026 01:39:52 GMT</pubDate><ttl>60</ttl><item><title>在类定义中实现对私有数据成员的隐藏</title><link>http://www.cppblog.com/iwong/archive/2008/08/11/58441.html</link><dc:creator>iwong</dc:creator><author>iwong</author><pubDate>Sun, 10 Aug 2008 17:32:00 GMT</pubDate><guid>http://www.cppblog.com/iwong/archive/2008/08/11/58441.html</guid><wfw:comment>http://www.cppblog.com/iwong/comments/58441.html</wfw:comment><comments>http://www.cppblog.com/iwong/archive/2008/08/11/58441.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iwong/comments/commentRss/58441.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iwong/services/trackbacks/58441.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 使用指针的重解释转换可以访问类的私有数据成员。<br><br>但在实际应用中，如果你写的类考虑周全，功能完善的话，类的用户没有必要通过这种方式来访问类的私有成员。同时类的用户自己也有对安全的诉求，因此也一般不会通过此种非正常方式来随意访问类的私有成员。<br><br>但是，这里又要提到“但是在实际应用中”——你也许无法一次写出一个完全可靠的类，不可避免地会在以后的编码中逐步对类进行不同程度的修改，有时甚至会大刀阔斧地删除多余的成员，增加其他新的成员。这时头文件就会改变，类成员的地址偏移也会发生变化。你需要向其他编码者更新你的头文件，其他文件中如果用到你的这个类，那么这些文件就需要重新编译、连接，很多问题随之而来。<br><br>现在我们要做的就是最大可能地隐藏数据成员的细节，只在头文件中展示使用这个类最必要的部分。&nbsp;&nbsp;<a href='http://www.cppblog.com/iwong/archive/2008/08/11/58441.html'>阅读全文</a><img src ="http://www.cppblog.com/iwong/aggbug/58441.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iwong/" target="_blank">iwong</a> 2008-08-11 01:32 <a href="http://www.cppblog.com/iwong/archive/2008/08/11/58441.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过指针访问类的私有数据成员</title><link>http://www.cppblog.com/iwong/archive/2008/08/10/58440.html</link><dc:creator>iwong</dc:creator><author>iwong</author><pubDate>Sun, 10 Aug 2008 06:06:00 GMT</pubDate><guid>http://www.cppblog.com/iwong/archive/2008/08/10/58440.html</guid><wfw:comment>http://www.cppblog.com/iwong/comments/58440.html</wfw:comment><comments>http://www.cppblog.com/iwong/archive/2008/08/10/58440.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/iwong/comments/commentRss/58440.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iwong/services/trackbacks/58440.html</trackback:ping><description><![CDATA[我们知道在C++中，为了防止某些数据成员或成员函数从外部被直接访问，可以将它们声明为private，这样编译器会阻止任何来自外部非友元的直接访问。<br><br>那么我们真的就没办法直接修改类的私有数据成员了吗？<br><br>来看一段代码：<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;a&nbsp;&amp;&nbsp;b&nbsp;are&nbsp;private&nbsp;members&nbsp;of&nbsp;class&nbsp;A</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a;<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;b;<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;initialize&nbsp;a&nbsp;&amp;&nbsp;b&nbsp;as&nbsp;value&nbsp;0</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A()&nbsp;:&nbsp;a(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">),&nbsp;b(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;{}<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;for&nbsp;display&nbsp;the&nbsp;value&nbsp;of&nbsp;a&nbsp;&amp;&nbsp;b</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;GetA();<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;GetB();<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">};<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;A::GetA()<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;a;<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">}<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">26</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;A::GetB()<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;b;<br></span><span style="COLOR: #008080">29</span>&nbsp;<span style="COLOR: #000000">}<br></span><span style="COLOR: #008080">30</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">31</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br></span><span style="COLOR: #008080">32</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">33</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;test;<br></span><span style="COLOR: #008080">34</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">35</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">before&nbsp;pointer&nbsp;access:\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">36</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;test.a&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;test.GetA()&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">37</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;test.b&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;test.GetB()&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br></span><span style="COLOR: #008080">38</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">39</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;access&nbsp;object&nbsp;test&nbsp;of&nbsp;class&nbsp;A&nbsp;by&nbsp;pointer</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">40</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;privateA&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;reinterpret_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">Test);<br></span><span style="COLOR: #008080">41</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;privateB&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;reinterpret_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">Test)&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">42</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">43</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;value&nbsp;changing&nbsp;by&nbsp;pointer!</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">44</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">privateA&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">45</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">privateB&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2.5</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">46</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">47</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">after&nbsp;pointer&nbsp;access:\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">48</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;test.a&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;test.GetA()&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">49</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;test.b&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;test.GetB()&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br></span><span style="COLOR: #008080">50</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">51</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">52</span>&nbsp;<span style="COLOR: #000000">}<br></span><span style="COLOR: #008080">53</span>&nbsp;<span style="COLOR: #000000"></span></div>
<p><br>运行后输出结果为：<br>before pointer access:<br>&nbsp;test.a = 0<br>&nbsp;test.b = 0</p>
<p>after pointer access:<br>&nbsp;test.a = 1<br>&nbsp;test.b = 2.5<br><br>可以看到，虽然我们已经将 A::a 和 A::b声明为 private ，但在强大的指针面前，类的任何细节都暴露无遗。<br><br>某种程度上，类的一个对象可以看作包含不同类型元素的数组，其数据成员的地址偏移由数据成员在类定义中的顺序决定——类对象的地址指向类中第一个被定义的数据成员的地址；第二个被定义的数据成员的地址取决于第一个数据成员的类型，若第一个为 int 型，则再偏移 4 个字节( sizeof(int) )即得到第二个数据成员的地址（有时也不一定是这样，如上例中，由于类型对齐的缘故，实际偏移 8 个字节( sizeof(double)&nbsp;)才得到第二个数据成员的地址，具体内容不在本文讨论范围内）。<br><br>所以即使你将其他所有细节都隐藏在 cpp 中，但头文件中不可避免地会出现私有数据成员的声明。而类的其他用户只要能看到这个声明，就能推算出类中各数据成员的相对地址偏移，从而用指针轻松实现对私有成员的访问。<br><br>上例只对私有数据成员进行了验证，有兴趣的可以试试看用函数指针能否访问私有成员函数。 </p>
<img src ="http://www.cppblog.com/iwong/aggbug/58440.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iwong/" target="_blank">iwong</a> 2008-08-10 14:06 <a href="http://www.cppblog.com/iwong/archive/2008/08/10/58440.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>