﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-小丐的blog-随笔分类-我的读书笔记</title><link>http://www.cppblog.com/qzb2006e/category/2343.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 10 Oct 2008 05:22:08 GMT</lastBuildDate><pubDate>Fri, 10 Oct 2008 05:22:08 GMT</pubDate><ttl>60</ttl><item><title>关于javascript callback</title><link>http://www.cppblog.com/qzb2006e/archive/2008/10/09/63532.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Thu, 09 Oct 2008 04:29:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2008/10/09/63532.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/63532.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2008/10/09/63532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/63532.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/63532.html</trackback:ping><description><![CDATA[如果注册了客户端回调脚本，则Form中如下字段不为空<br>Page.Request.Form["__CALLBACKID"]<br>Page.Request.Form["__CALLBACKPARAM"]<br><br><img src ="http://www.cppblog.com/qzb2006e/aggbug/63532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2008-10-09 12:29 <a href="http://www.cppblog.com/qzb2006e/archive/2008/10/09/63532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于HttpApplication</title><link>http://www.cppblog.com/qzb2006e/archive/2008/09/19/62257.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Fri, 19 Sep 2008 03:00:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2008/09/19/62257.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/62257.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2008/09/19/62257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/62257.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/62257.html</trackback:ping><description><![CDATA[修改web.config<br>Session_End<br>Application_End<br>刷新页面<br>Application_Start<br>Application_BeginRequest<br>Application_AuthenticateRequest<br>Session_Start<br>再次刷新<br>Application_BeginRequest<br>Application_AuthenticateRequest<br><img src ="http://www.cppblog.com/qzb2006e/aggbug/62257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2008-09-19 11:00 <a href="http://www.cppblog.com/qzb2006e/archive/2008/09/19/62257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如果sharepoint 不能卸载</title><link>http://www.cppblog.com/qzb2006e/archive/2008/08/16/59009.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sat, 16 Aug 2008 00:56:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2008/08/16/59009.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/59009.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2008/08/16/59009.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/59009.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/59009.html</trackback:ping><description><![CDATA[执行命令行 Stsadm -o uninstall 然后在控制面板里面卸载即可。<br><img src ="http://www.cppblog.com/qzb2006e/aggbug/59009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2008-08-16 08:56 <a href="http://www.cppblog.com/qzb2006e/archive/2008/08/16/59009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>修复Visual Studio</title><link>http://www.cppblog.com/qzb2006e/archive/2008/07/24/57007.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Wed, 23 Jul 2008 16:06:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2008/07/24/57007.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/57007.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2008/07/24/57007.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/57007.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/57007.html</trackback:ping><description><![CDATA[<span class="forumName"><font size="2" face="Courier New">有时候在添加Web引用的时候，会告诉你没有安装有关组件，需要重装Visual Studio，主要是因为所安装的扩展包出了问题，这时候可以用<br>devenv /resetskippkgs<br>修复<br></font></span><img src ="http://www.cppblog.com/qzb2006e/aggbug/57007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2008-07-24 00:06 <a href="http://www.cppblog.com/qzb2006e/archive/2008/07/24/57007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Nebula Tips (1)</title><link>http://www.cppblog.com/qzb2006e/archive/2008/07/19/56635.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sat, 19 Jul 2008 13:27:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2008/07/19/56635.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/56635.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2008/07/19/56635.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/56635.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/56635.html</trackback:ping><description><![CDATA[可以在E:\Program Files\Nebula2 SDK\build\vstudio8目录找到编译的项目。<br>其中：Nebula2.sln是源代码<br>tutorials.sln是那些小例子<br>打开tutorials.sln（我用的是VS2008)，找到你要运行的那个项目（可以在SDK找对应的例子），设置一下包含路径和库(lib)路径，就可以编译了，通常编译过程会很顺利，但是我这里运行的时候，出现了 ：<br>
<pre style="margin-top: 0pt; display: inline;">nD3D9Shader:failed to load fx file 'h:/games/Nebula2SDK/data/shaders/fixed/shape.fx' with:<br>memory(34,9):ID3DXEffectCompiler:Error in type checking<br>memory(55,9):ID3DXEffectCompiler:Error in type checking<br>memory(67,9):ID3DXEffectCompiler:Error in type checking<br>ID3DXEffectCompiler:There was an error initializing the compiler<br>在http://nebuladevice.cubik.org/forum/index.php?topic=41.msg401#msg401可以找到解决办法，其中有效的一条是在nd3d9shader_main.cc<br>中设置编译标识为<br>D3DXSHADER_USE_LEGACY_D3DX9_31_DLL<br>找到方法bool nD3D9Shader::LoadResource()<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">/*</span><span style="color: #008000;">*<br>&nbsp;&nbsp;&nbsp;&nbsp;Load&nbsp;D3DX&nbsp;effects&nbsp;file.<br></span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">bool</span><span style="color: #000000;"><br>nD3D9Shader::LoadResource()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;n_assert(</span><span style="color: #000000;">!</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">IsLoaded());<br>&nbsp;&nbsp;&nbsp;&nbsp;n_assert(</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">effect);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;HRESULT&nbsp;hr;<br>&nbsp;&nbsp;&nbsp;&nbsp;IDirect3DDevice9</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;d3d9Dev&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">refGfxServer</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">d3d9Device;<br>&nbsp;&nbsp;&nbsp;&nbsp;n_assert(d3d9Dev);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;mangle&nbsp;path&nbsp;name</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;nString&nbsp;filename&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">GetFilename();<br>&nbsp;&nbsp;&nbsp;&nbsp;nString&nbsp;mangledPath&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;nFileServer2::Instance()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">ManglePath(filename.Get());<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">load&nbsp;fx&nbsp;file<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;nFile</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;file&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;nFileServer2::Instance()</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">NewFileObject();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;open&nbsp;the&nbsp;file</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">file</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Open(mangledPath.Get(),&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">r</span><span style="color: #000000;">"</span><span style="color: #000000;">))<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_error(</span><span style="color: #000000;">"</span><span style="color: #000000;">nD3D9Shader:&nbsp;could&nbsp;not&nbsp;load&nbsp;shader&nbsp;file&nbsp;'%s'!</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;mangledPath.Get());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;get&nbsp;size&nbsp;of&nbsp;file</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;fileSize&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;file</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">GetSize();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;allocate&nbsp;data&nbsp;for&nbsp;file&nbsp;and&nbsp;read&nbsp;it</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;buffer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;n_malloc(fileSize);<br>&nbsp;&nbsp;&nbsp;&nbsp;n_assert(buffer);<br>&nbsp;&nbsp;&nbsp;&nbsp;file</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Read(buffer,&nbsp;fileSize);<br>&nbsp;&nbsp;&nbsp;&nbsp;file</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Close();<br>&nbsp;&nbsp;&nbsp;&nbsp;file</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Release();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;ID3DXBuffer</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;errorBuffer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">#if</span><span style="color: #000000;">&nbsp;N_D3D9_DEBUG</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;compileFlags&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;D3DXSHADER_DEBUG&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;D3DXSHADER_SKIPOPTIMIZATION;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">#else</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight: bold; color: red;">DWORD&nbsp;compileFlags&nbsp;</span></span><span style="color: red; font-weight: bold;">=</span><span style="color: #000000;"><span style="font-weight: bold; color: red;">&nbsp;D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">#endif</span><span style="color: #000000;"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;create&nbsp;include&nbsp;file&nbsp;handler</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;nString&nbsp;shaderPath(mangledPath.Get());<br>&nbsp;&nbsp;&nbsp;&nbsp;nD3D9ShaderInclude&nbsp;includeHandler(shaderPath.ExtractDirName());<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;get&nbsp;global&nbsp;effect&nbsp;pool&nbsp;from&nbsp;gfx&nbsp;server</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;ID3DXEffectPool</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;effectPool&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">refGfxServer</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">GetEffectPool();<br>&nbsp;&nbsp;&nbsp;&nbsp;n_assert(effectPool);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;create&nbsp;effect</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;hr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;D3DXCreateEffect(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d3d9Dev,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;pDevice</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;pFileData</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fileSize,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;DataSize</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;pDefines</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">includeHandler,&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;pInclude</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;compileFlags,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Flags</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;effectPool,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;pPool</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">effect),&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;ppEffect</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">errorBuffer);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;ppCompilationErrors</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;n_free(buffer);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(FAILED(hr))<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_error(</span><span style="color: #000000;">"</span><span style="color: #000000;">nD3D9Shader:&nbsp;failed&nbsp;to&nbsp;load&nbsp;fx&nbsp;file&nbsp;'%s'&nbsp;with:\n\n%s\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mangledPath.Get(),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;errorBuffer&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;errorBuffer</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">GetBufferPointer()&nbsp;:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">No&nbsp;D3DX&nbsp;error&nbsp;message.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(errorBuffer)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;errorBuffer</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">Release();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;n_assert(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">effect);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;success</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">hasBeenValidated&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">didNotValidate&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">SetState(Valid);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;validate&nbsp;the&nbsp;effect</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">ValidateEffect();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">;<br>}</span></div>
注意按照红色的地方进行修改即可，然后就回看到运行结果：<br><img alt=""  src="http://www.cppblog.com/images/cppblog_com/qzb2006e/nebulat1.JPG" width="648" height="514"><br><br></pre>
<img  src="file:///E:/DOCUME~1/qzb/LOCALS~1/Temp/moz-screenshot.jpg" alt=""><br><br><img src ="http://www.cppblog.com/qzb2006e/aggbug/56635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2008-07-19 21:27 <a href="http://www.cppblog.com/qzb2006e/archive/2008/07/19/56635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javascript学习</title><link>http://www.cppblog.com/qzb2006e/archive/2008/04/23/47877.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Wed, 23 Apr 2008 03:17:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2008/04/23/47877.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/47877.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2008/04/23/47877.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/47877.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/47877.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span lang="EN-US"><span>1、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;
</span></span></span><!--[endif]--><span lang="EN-US">Html</span><span style="font-family: 宋体;">标签如果环绕</span><span lang="EN-US">javascript</span><span style="font-family: 宋体;">代码，则会作用于它的输出</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">如：</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;html&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;head&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;script
type="text/javascript"&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US">function sayhello()</span></p>
<p class="MsoNormal"><span lang="EN-US">{</span></p>
<p class="MsoNormal"><span lang="EN-US">document.write("hello");</span></p>
<p class="MsoNormal"><span lang="EN-US">}</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;/script&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;/head&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;body&gt;</span></p>
<p class="MsoNormal"><strong><span lang="EN-US">&lt;font
size="100"&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span lang="EN-US">&lt;script
language="javascript"&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span lang="EN-US">sayhello();<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span lang="EN-US">&lt;/script&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span lang="EN-US">&lt;/font&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><span lang="EN-US">&lt;/body&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;/html&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span lang="EN-US"><span>2、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;
</span></span></span><!--[endif]--><span lang="EN-US">&lt;script language=&#8221;javascript&#8221;&gt;&lt;/script&gt;</span><span style="font-family: 宋体;">不是</span><span lang="EN-US">W3C</span><span style="font-family: 宋体;">标准</span></p>
<p class="MsoNormal"><span lang="EN-US">W3C</span><span style="font-family: 宋体;">标准是：</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;script type=&#8221;text/javascript&#8221;&gt;&lt;/script&gt;</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">但是有些浏览器不支持</span><span lang="EN-US">type</span><span style="font-family: 宋体;">方式声明</span><span lang="EN-US">javascript</span><span style="font-family: 宋体;">脚本，所以你最好两个都用，就如下面：</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;script language=&#8221;javascript&#8221; type=&#8221;text/javascript&#8221;&gt;&lt;/script&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span lang="EN-US"><span>3、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;
</span></span></span><!--[endif]--><span style="font-family: 宋体;">有些浏览器在执行脚本的过程中产生输出，但有些不能</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;body&gt;</span></p>
<p class="MsoNormal"><strong><span style="color: red;" lang="EN-US">&lt;h1&gt;Ready start&lt;/h1&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span style="color: red;" lang="EN-US">&lt;script type="text/javascript"&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span style="color: red;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>alert("First
Script Ran");<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span style="color: red;" lang="EN-US">&lt;/script&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><span lang="EN-US">&lt;h2&gt;Running...&lt;/h2&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;script
type="text/javascript"&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>alert("Second Script Ran");</span></p>
<p class="MsoNormal"><span lang="EN-US">&lt;/script&gt;</span></p>
<p class="MsoNormal"><strong><span style="color: #3366ff;" lang="EN-US">&lt;h2&gt;Keep running&lt;/h2&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span style="color: #3366ff;" lang="EN-US">&lt;script type="text/javascript"&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span style="color: #3366ff;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>alert("Third Script Ran");<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span style="color: #3366ff;" lang="EN-US">&lt;/script&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><strong><span style="color: #3366ff;" lang="EN-US">&lt;h1&gt;Stop!&lt;/h1&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><span lang="EN-US">&lt;/body&gt;</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span lang="EN-US"><span>4、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;
</span></span></span><!--[endif]--><span style="font-family: 宋体;">大多数浏览器喜欢把它们不支持的标签中的内容直接显示出来，如果你碰到一个浏览器恰好不支持</span><span lang="EN-US">javascript</span><span style="font-family: 宋体;">，你应该：</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&lt;script type="text/javascript"&gt;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&lt;!-- <o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>put your
JavaScript here<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">//--&gt;<o:p></o:p></span></strong></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&lt;/script&gt;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">但是如果你所写的是严格的<span lang="EN-US">XHTML</span>，注释标记就不大合适了，你最好：<span lang="EN-US"><o:p></o:p></span></span></p>
<pre><span lang="EN-US">&lt;<strong>script type="text/javascript"</strong>&gt;</span></pre>
<pre><span lang="EN-US">&lt;<strong>![CDATA[</strong></span></pre>
<pre><strong><span lang="EN-US"><span>&nbsp;&nbsp; </span></span></strong><span lang="EN-US">..script here ..</span></pre>
<pre><strong><span lang="EN-US">]]</span></strong><span lang="EN-US">&gt;</span></pre>
<pre><span lang="EN-US">&lt;<strong>/script</strong>&gt;</span></pre>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span lang="EN-US"><span>5、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;
</span></span></span><!--[endif]--><span style="font-family: 宋体;">如果浏览器不支持</span><span lang="EN-US">javascript</span><span style="font-family: 宋体;">或者</span><span lang="EN-US">javascript</span><span style="font-family: 宋体;">被关闭了，最好写一段</span><span lang="EN-US">noscript</span><span style="font-family: 宋体;">，就像这样：</span></p>
<pre><strong><span lang="EN-US">&lt;noscript&gt;<o:p></o:p></span></strong></pre>
<pre><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;em&gt;Either your browser does not support JavaScript or it</span></pre>
<pre><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>is currently disabled.&lt;/em&gt;</span></pre>
<pre><strong><span lang="EN-US">&lt;/noscript&gt;<o:p></o:p></span></strong></pre>
<p class="MsoNormal"><span style="font-family: 宋体;">一个很有意思的用法就是，如果浏览器不支持</span><span lang="EN-US">javascript</span><span style="font-family: 宋体;">，就让他们跳转到一个错误页面，如下：</span></p>
<pre><span lang="EN-US">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" </span></pre>
<pre><span lang="EN-US">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;</span></pre>
<pre><span lang="EN-US">&lt;html xmlns="http://www.w3.org/1999/xhtml" lang="en"&gt;</span></pre>
<pre><span lang="EN-US">&lt;head&gt;</span></pre>
<pre><span lang="EN-US">&lt;title&gt;noscript Redirect Demo&lt;/title&gt;</span></pre>
<pre><span lang="EN-US">&lt;meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /&gt;</span></pre>
<pre><span lang="EN-US">&lt;!--<span>&nbsp; </span>warning example does not validate --&gt;</span></pre>
<pre><strong><span lang="EN-US">&lt;noscript&gt;<o:p></o:p></span></strong></pre>
<pre><strong><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;meta http-equiv="Refresh" content="0;URL=/errors/noscript.html" /&gt;<o:p></o:p></span></strong></pre>
<pre><strong><span lang="EN-US">&lt;/noscript&gt;<o:p></o:p></span></strong></pre>
<pre><span lang="EN-US">&lt;/head&gt;<a name="26"></a>
<pre><span lang="EN-US">&lt;body&gt;</span></pre>
<pre><span lang="EN-US">&lt;script type="text/javascript"&gt;</span></pre>
<pre><span lang="EN-US">&lt;!--</span></pre>
<pre><span lang="EN-US"> document.write("Congratulations! If you see this you have JavaScript.");</span></pre>
<pre><span lang="EN-US">//--&gt;</span></pre>
<pre><span lang="EN-US">&lt;/script&gt;</span></pre>
<pre><span lang="EN-US">&lt;noscript&gt;</span></pre>
<pre><span lang="EN-US"><span>&nbsp;&nbsp; </span>&lt;h2&gt;Error: JavaScript required&lt;/h2&gt;</span></pre>
<pre><span lang="EN-US"><span>&nbsp;&nbsp; </span>&lt;p&gt;Read how to &lt;a href="/errors/noscript.html"&gt;rectify this problem&lt;/a&gt;.&lt;/p&gt;</span></pre>
<pre><span lang="EN-US">&lt;/noscript&gt;</span></pre>
<pre><span lang="EN-US">&lt;/body&gt;</span></pre>
<pre><span lang="EN-US">&lt;/html&gt;</span></pre>
<pre><span lang="EN-US"><o:p>&nbsp;</o:p></span></pre>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><span lang="EN-US"><span>6、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;
</span></span></span><!--[endif]--><span style="font-family: 宋体;">事件响应方面，</span><span lang="EN-US">html</span><span style="font-family: 宋体;">是不区分大小写的，</span><span lang="EN-US">onclick,OnClick,onCliCk</span><span style="font-family: 宋体;">效果相同，但是在</span><span lang="EN-US">XHTML</span><span style="font-family: 宋体;">中，只接受小写。</span></p>
<pre>大多数浏览器支持在地址栏中输入如<strong><span lang="EN-US">javascript: alert('hello')</span>的代码来运行<span lang="EN-US">javascript</span>。</strong>当然，也可以以超链接的形式：<strong><span lang="EN-US">&lt;a href="javascript: alert('hello I am a pseudo-URL script');"&gt;Click to invoke&lt;/a&gt;</span></strong></pre>
</span></pre><img src ="http://www.cppblog.com/qzb2006e/aggbug/47877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2008-04-23 11:17 <a href="http://www.cppblog.com/qzb2006e/archive/2008/04/23/47877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Direct Show 笔记</title><link>http://www.cppblog.com/qzb2006e/archive/2008/02/22/43108.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Fri, 22 Feb 2008 14:10:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2008/02/22/43108.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/43108.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2008/02/22/43108.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/43108.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/43108.html</trackback:ping><description><![CDATA[<p><b>一、 </b><b>总览：</b> <p>Graph、Filter、Pin、Simple <p>Graph：可以理解为媒体处理的流程图。 <p>Filter：可以理解为媒体处理流程图中的一个步骤。 <p>Pin：可以理解为媒体处理各个步骤之间的数据流节点。 <p>Simple：可以理解为各个形态的数据。 <p><img height="233" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/DirectShow_1375F/clip_image002.jpg" width="553"> <p>Filter的分类： <p>· <i>source</i> filter:将数据从源（比如媒体文件）引入Graph。 <p>· <i>transform</i> filter：数据流入、改变、流出。 <p>· <i>Renderer</i> filters：把最终结果展现给用户。 <p>· <i>splitter</i> filter：比如把一个媒体流分解为视频和音频。 <p>· <i>mux</i> filter：和splitter filter相反。 <p><b>1. </b><b>Graph Manager</b> <p>主要对处于同一个Graph的Filter(s)进行统一的管理。 <p>比如： <p>· <i>各个</i><i>Filter</i><i>的状态切换</i> <p>· <i>建立同步时钟</i> <p>· <i>事件回发</i> <p>· <i>创建</i> <p>为什么要统一管理状态切换？ <p>因为处于同一Graph中的各个Filter的状态切换往往需要遵循严格的先后顺序。所以一般通过发送命令给Graph Manager的方式进行各Filter的状态变更。 <p>为什么要建立同步时钟？ <p>比如声像需要同步。 <p>2. <b>Media Types</b> <p>结构体<a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/am_media_typestructure.htm"><b>AM_MEDIA_TYPE</b></a>定义了媒体类型。 <p>主要包含如下结构： <p>· <i>Major type:</i> 由一个GUID来表示。通常包含音视频、未知流、MIDI等等。 <p>· <i>Subtype:</i> 由一个GUID来表示。Major type为视频，则子类型可以包括RGB-24, RGB-32, UYVY <p>· <i>Format block:</i> 说明图形尺寸、帧率等信息。如果Major type为视频，sub type为RGB-24，则Format block的信息会被自动辨识。 <p><b>3. </b><b>Sample</b><b>和</b><b>Allocator</b><b></b> <p>需要注意的是，各个filter之间并不直接传送它们各自进行处理的数据的指针。它们通过一个暴露<a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/imemallocatorinterface.htm"><b>IMemAllocator</b></a>接口的Com组件来分配内存。填充了数据的内存被封装到Sample里面。各个Filter真正使用的是Sample。Sample通常包含： <p>· 内存指针 <p>· 时间戳 <p>· 标识 <p>· 媒体类型（可选） <p>这里当一个Filter使用Sample的时候，它同时掌握这个Sample的引用计数，这样就有效杜绝了资源争用现象的发生。 <p><b>4. </b><b>Filter Graph</b><b>中的硬件</b> <p>硬件被封装到Filter中，任何与硬件的交互都转化为与Filter的交互。 <p><b>二、 </b><b>Graph-Building </b><b>组件</b> <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/filtergraphmanager.htm">Filter Graph Manager</a>. <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/capturegraphbuilder.htm">Capture Graph Builder</a>：设计的初衷是视频捕获,但是可以衍生很多用途。 <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/filtermapper.htm">Filter Mapper</a> and <a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/systemdeviceenumerator.htm">System Device Enumerator</a>：枚举可用的filter. <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/dvdgraphbuilder.htm">DVD Graph Builder</a> <p>Video Control <p><b>1. </b><b>智能拼接</b> <p>1) 如果在Graph里面有一个没有输入的Filter，那么Graph在完成自己的时候，就会考虑这个Filter。如果有一个已有的Filter的流出恰好与这个没有输入的Filter的流入相匹配，则将这两个Filter连接。 <p>2) Graph在完成自己的过程中也会查找所有注册过的Filter与当前非终点Filter的流出进行匹配。注册的Filter会有一个权值，作为Graph进行连接尝试的优先级依据。 <p>步骤： <p>1) 使用IStreamBuilder（如果pin实现了这个接口，但大多数情况没有）。（否则2） <p>2) 查找被缓存的Filter。（否则3） <p>3) 查找Graph现有的Filter。（否则4） <p>4) 查找所有注册了的Filter。 <p><b>2. </b><b>关键方法</b> <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/ifiltergraphconnectdirect.htm"><b>IFilterGraph::ConnectDirect</b></a>:直接连接两个Filter，如不成功，返回失败。 <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/igraphbuilderconnect.htm"><b>IGraphBuilder::Connect</b></a>：连接两个Filter，如果可能，直接连接，否则通过中间Filter(s)进行连接。 <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/igraphbuilderrender.htm"><b>IGraphBuilder::Render</b></a>：你自己建立了一系列从源开始的Filter，基于这些Filter(s)完成Graph。 <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/igraphbuilderrenderfile.htm"><b>IGraphBuilder::RenderFile</b></a>：从一个文件开始完成Graph. <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/ifiltergraphaddfilter.htm"><b>IFilterGraph::AddFilter</b></a>:向Graph中添加一个Filter <p>通过这些方法，你可以： <p>1、 由Graph Manager建立整个Graph。（通过RenderFile） <p><b>2、 </b>由Graph Manager建立部分Graph。（比如你想自己写一个AVI文件，当然也可以通过Render来生成预览）<b></b> <p><b>3、 </b>完全手动建立整个Graph。（需要自己AddFilter，还需要自己Connect）。<b></b> <p><b>三、 </b><b>Direct Show </b><b>数据流概述</b> <p>1. <b>关键接口（方法）</b> <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/imediasampleinterface.htm"><b>IMediaSample</b></a>：对Filter之间使用的内存的封装。 <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/imemallocatorgetbuffer.htm"><b>IMemAllocator::GetBuffer</b></a>：从allocator获取Buffer（即ImediaSimple的实现对象） <p>摘要： <p>由于Render会按照时间戳来Render数据，所以它会一直占用它的上一级Filter流入的Simple，直到时间戳所标识的时间到达。所以当上一级Filter用完了allocator的Simple池中的Simple时，会阻塞而不处理，进而反向影响到更上一级的Filters，从而使它们变为等待的状态。同时由于时间戳对于Render的时间上的要求，所有上级Render都必须在Simple的时间戳标识的时间到达之前处理完自己对于该Simple的动作。 <p><b>2. </b><b>Transport</b><b>（传送）</b> <p>· Push Model（推送模型）：上层filter（pin-out）将处理好的数据推送给下层filter(pin-in)。下层filter在需要数据的时候通过<a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/imeminputpinreceive.htm"><b>IMemInputPin::Receive</b></a>来获取数据。 <p>· Pull Model（抓取模型）：下层filter(pin-in)在需要数据的时候，通过<a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/iasyncreaderinterface.htm"><b>IAsyncReader</b></a>异步向上层filter请求数据。（通常用于视频文件的回放） <p><b>3. </b><b>Samples and Allocators</b> <p>1) 引用计数 <p>上层Filter(pin-out)通过<a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/imemallocatorgetbuffer.htm"><b>IMemAllocator::GetBuffer</b></a>向Allocator申请Simple，如果此时没有Simple的引用计数为0，则说明Allocator的Simple池中没有可用的Simple，则GetBuffer的调用会被阻塞。一旦Simple池中出现可用的Simple，则先前阻塞的GetBuffer放行，并获取一个引用计数变为1的Simple。此Simple处理后，传递给下层Filter(pin-in)，下层Filter如果在Receive方法中处理Simple，则它与上层Filter的处理处于同一线程中，Simple的引用计数不会变化，如果下层Filter需要通过创建线程异步使用上层推入的Simple进行处理，则该Simple的引用计数会加1，变为2.之后如果上层Filter的推送线程结束，则Simple的引用计数减1，变为1. <p>2) 提交和撤销Allocator <p><a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/imemallocatorcommit.htm"><b>IMemAllocator::Commit</b></a>,在被调用之前，所有的GetBuffer无效， <p>调用<a href="ms-help://MS.PSDKSVR2003SP1.1033/directshow/htm/imemallocatordecommit.htm"><b>IMemAllocator::Decommit</b></a>之后，所有的GetBuffer调用无效. <p><b>4. </b><b>Filter </b><b>状态变化</b><b></b> <p>Filter状态的变化由Graph Manager进行控制。 <p>所有的状态变化都是自低（Render Filter）向上（Source Filter）进行的。比如暂停的时候，Render Filter会首先暂停，这时候Render之上的Filter中都会存有未能推送的Simple，此时相当于在各个Filter之前都堆积了一些等待处理的数据。沿着Render向上的Filter逐个暂停，直到Source。当状态从暂停变化为开始的时候，Render会首先变化为开始状态，处理在它之前堆积的数据，并释放那些被占用的Simple。然后逐步向上直到Source,Source在能够获取Simple之后，数据继续流入Graph，整个Graph进入开始状态。</p><img src ="http://www.cppblog.com/qzb2006e/aggbug/43108.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2008-02-22 22:10 <a href="http://www.cppblog.com/qzb2006e/archive/2008/02/22/43108.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--重构关系型数据库（1）</title><link>http://www.cppblog.com/qzb2006e/archive/2007/08/10/29529.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Fri, 10 Aug 2007 14:47:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/08/10/29529.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/29529.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/08/10/29529.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/29529.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/29529.html</trackback:ping><description><![CDATA[<p>1、数据库与面向对象编程语言的不同<br>关系数据库的关注点是数据结构的声明。这样的话一些封装手段就不可用了。没有封装，数据访问就不会被明显的约束。<br>表是通过外键关联的。这同样不能够被封装。<br>存在于数据库中的数据是持久化的，并且存活得比程序要长。数据库的结构一旦发生变化，数据就要进行迁徙。</p>
<p>如果系统被多次安装，那么就会有不同的数据库。那么如果数据库结构发生变化，这个变化同样要作用于每一份安装。</p>
<p>不同的用户可以同时访问数据，但是他们可以每人拥有一份程序的拷贝。<br><br>类可以继承，但数据不行。<br>源代码可以在本地进行维护和测试，之后发布到源代码管理服务器中。版本冲突可以被识别到，然后通过一些强有力的工具可以帮助解决这些问题。在大多数项目中，同一个数据库往往为多个开发人员服务。<br>维护源代码可以使用工具。数据库的结构和数据则只能够由人花更多的精力去维护。<br>访问数据库所花费的时间比起访问访问内存中对象的时间来要多上好几倍。</p>
<p>关系型数据库中的数据结构是浅层结构，然而当它们变成对象处于面向对象的系统中时，他们的含义变得更加深入，他们的关系变得更加错综复杂。</p>
<p>2程序与数据库打交道时产生的一些问题</p>
<p>当程序与数据库交互时，会产生这样一些问题：</p>
<p>程序与数据库之间的关联往往不是类型安全的（想象JDBC）。编译器无法评估程序与数据库是否结构性兼容。某些映射类和持久层把这些问题拿到了一边，却没有解决它们。类型安全性将会在影射类或持久层中失去，而不是其他的地方。</p>
<p>数据库将会&#8220;隐藏&#8221;一些对象。这种情况发生在对象被写入数据库或者在读取出来的地方。因此对象可以被程序的两个部分交换使用，而不需要显式得暴露于接口中。</p>
<p>大多数情况下往往采用表和对象一一对应的模式。这往往在强调数据的应用程序中是错误的做法。特别是当需要从数据库读取对象时，可能会需要多个表的极联，或者为了满足数据展示的需要，建立一些视图。结果，当数据库发生变化时，很难找到一个合适的途径来决定那些类也要跟着修改。反过来说，通常无法明确类的那些变化会影响到查询和视图。</p>
<p>还有一些琐碎的问题。数据库中的数据类型与程序语言中的基本数据类型之间的映射会造成一些困难。比如时间戳的尺度，采用浮点数尺度或采用string或变长字符串集合就会有相当大的差别。</p>
<p>在面向对象的系统当中，关联关系的建模是基于概念的（例如，账目和收支有关）。在关系数据库中，一对多关系和多对一关系都是适用的。所以也就无法找到一套确定的方案来实施重构。</p>
<p>因此我们在重构的时候需要着重考虑这样三个地方：</p>
<p>1）有关数据库结构、数据库模型的重构；</p>
<p>2）不同版本的数据库之间的数据迁移；</p>
<p>3）有关数据库访问代码的重构。</p>
<p>3重构关系数据库的数据库结构</p>
<p>在实践中，往往有一定数量的数据库模式平行存在。至少有两个模式：一个为开发者所使用（开发数据库）一个为用户所使用（产品数据库）。</p>
<p>因此开发者总是可以尝试着修改数据库而不去惊扰用户。只有当数据库被彻底的测试完成，并且适合于构建与其上的系统，这样才会将数据库、程序作为一个稳定版本提交给用户。</p>
<p>此外，每一个开发者应当拥有自己的数据库实例，这样他们才能够独立的测试他们对于数据库的一些变动而不会影响到开发团队的其他人员。这些不同版本数据库实例的存在使得数据的迁移变成了一个关键话题。在下面的部分，我们将会讨论这个话题。</p>
<p>&#8220;逐步进化&#8221;这样一个核心的原理不论在程序重构中还是数据结构的重构中都在重演着：老的结构并不会马上被新的所取代。新旧数据库结构往往会并存一段时间。老的数据库结构会被标记为&#8220;过期&#8221;以让那些新编写的程序不去访问它。然后已有的程序会被修改，一步又一步的向新数据库过渡。一旦这个过程结束，老的数据结构就算完成了它的使命，他会被终结然后删除。图5-1示出了表&#8220;Customer&#8221;的变革。一开始的时候，姓和名是作为一个字段存储的，他们合称作&#8220;Name&#8221;。现在姓和名会被存放在两个字段中，最后Name字段将被取代并被删除。</p>
<p><a href="http://www.cppblog.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/fa5a4f2dd143_13D19/dbrefactor.jpg" atomicselection="true"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=190 alt=dbrefactor src="http://www.cppblog.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/fa5a4f2dd143_13D19/dbrefactor_thumb.jpg" width=724 border=0></a> </p>
<p>在中间的状态，表Customer包含冗余字段Name。程序或触发器需要保障它们之间的一致性。</p>
<p>在Java中，你可以把那些过时的程序标记上&#8220;已过时&#8221;。但是在大多数数据库和其他程序开发语言中没有提供相关的功能。</p>
<p>在关系数据库中，字段、表、视图甚至整个数据库的结构都有可能需要被标记为&#8220;过时&#8221;，当然，这视具体的重构过程而定。我们往往通过访问层面的限制或提示来体现这些独立的&#8220;已过时&#8221;标注。比如我们使用O/R mapping工具来生成这些数据的映射类，那么对于这些类或方法我们就可以用&#8220;已过时&#8221;进行标记了。当然，前提就是你许诺不会通过其他的手段来直接访问数据库。如果确实这样，在你的下一个版本中使用这种方式标记&#8220;过时&#8221;的数据库结构也就足够了。</p>
<p>如果你无法保证对于数据库的访问只是通过O/R mapping的映射类，那么就和你的开发团队订立协议吧。列一张表，在这个表列举因为重构而过时的那些东西。当然所有的开发者都要同意这个表上列举的重构结果，并且能够去贯彻它。</p>
<p><a href="http://www.cppblog.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/fa5a4f2dd143_13D19/dbrefactor2.jpg" atomicselection="true"><img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=323 alt=dbrefactor2 src="http://www.cppblog.com/images/cppblog_com/qzb2006e/WindowsLiveWriter/fa5a4f2dd143_13D19/dbrefactor2_thumb.jpg" width=726 border=0></a> </p>
<p>&nbsp;</p>
<p>Ambler在他的网站上收集了很多数据库中会被频繁用到的重构方法。这些重构方法为数据库重构提供了一些依据。</p>
<p>Ambler的重构方法的目的在于为数据库的结构带来改观。因而只是独立的添加一列并不能组成一次重构。独立的添加一列不能够给数据库结构带来任何的改观。</p>
<p>有这样几种形式的重构：重构而提升数据的质量；重构而优化数据的结构；重构而提高数据的性能；重构而整合数据；重构而优化数据库框架。</p>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/29529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-08-10 22:47 <a href="http://www.cppblog.com/qzb2006e/archive/2007/08/10/29529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔记 第四章(1) </title><link>http://www.cppblog.com/qzb2006e/archive/2007/08/06/29242.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Mon, 06 Aug 2007 13:50:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/08/06/29242.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/29242.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/08/06/29242.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/29242.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/29242.html</trackback:ping><description><![CDATA[4.2JUnit框架<br>单元测试<br>编写单元测试的目的是为了<span style="BACKGROUND-COLOR: yellow">提高</span>身为一个程序员的生产性能。至于让质保部门开心，那只是附带效果而以。单元测试是<span style="BACKGROUND-COLOR: yellow">高度本地化</span>的东西，每个test class只对单一package运作。它能够测试其他packages的接口，除此之外它将假设其他package一切正常。<br>功能测试<br>用来保证软件能够正常运作。他们只负责向客户提供质量保证，并不关心程序员的生产力。它们应该由一个喜欢寻找臭虫的个别团队来开发。这个团队应该使用重量级<span style="BACKGROUND-COLOR: yellow">工具</span>和技术来帮助自己开发良好的功能测试。<br>一般而言，功能测试尽可能把整个系统当作一个黑箱。面对一个GUI待测系统，它们通过GUI来操作那个系统。而对文件更新程序或数据库更新程序，功能测试只观察<span style="BACKGROUND-COLOR: yellow">待定</span>输入所导致的数据变化。<br>一旦功能测试者或最终用户找到软件中的一个bug，要除掉它至少需要做两件事。当然你必须修改代码，才得以排除错误，但你还应该<span style="BACKGROUND-COLOR: yellow">添加</span>一个<span style="BACKGROUND-COLOR: yellow">单元测试</span>，让它<span style="BACKGROUND-COLOR: yellow">揭发</span>这只臭虫。<br>4.3添加更多的测试<br>观察class该做的所有事情，然后针对任何一项功能的任何一种可能失败的情况，进行测试。这不同于某些程序员提倡的&#8220;测试所有public函数&#8221;。记住，测试应该是一种<span style="BACKGROUND-COLOR: yellow">风险驱动</span>行为，测试的目的是希望找出现在或未来可能出现的错误。所以我不会去测试那些仅仅读或写一个值域的访问函数，因为它们太简单了，不大可能出错。这一点很重要，因为你如果撰写过多测试，结果往往测试量反而不够。测试的要诀是：测试你最担心出错的部分，这样你就能从测试工作中得到最大收益。<br>考虑可能出错的边界条件，把测试火力集中在那儿。<br>寻找边界条件，也包括寻找特殊的、可能导致测试失败的情况。对于文件相关测试，空文件是个不错的边界条件。当事情被大家认为应该会出错时，别忘了检查彼时是否有异常如预期般的被抛出。 <br>不要因为&#8220;测试无法捕捉所有臭虫&#8221;，就不撰写测试代码，因为测试的确可以捕捉大多数臭虫。<br>对象技术有个微妙处：继承和多态会让测试变得比较困难，因为将有许多组合需要测试。如果你有三个彼此合作的abstract class有三个subclass，那么你总共有九个可供选择的classes，和27种组合。我并不总是试着测试所有可能组合，但我会尽量测试<span style="BACKGROUND-COLOR: yellow">每一个</span>classes，这可以大大减少各种组合所造成的风险。如果这些classes之间彼此有合理的独立性，我很可能不会尝试所有组合。是的，我总有可能遗漏些什么，但我觉得&#8220;花合理时间抓出大多数臭虫&#8221;要好过&#8220;穷尽一生抓出所有臭虫&#8221;。<br>测试代码和产品代码之间有个区别：你可以放心的拷贝、编辑测试代码。
<img src ="http://www.cppblog.com/qzb2006e/aggbug/29242.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-08-06 21:50 <a href="http://www.cppblog.com/qzb2006e/archive/2007/08/06/29242.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔记 第三章(6)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/07/30/28662.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Mon, 30 Jul 2007 14:11:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/07/30/28662.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/28662.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/07/30/28662.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/28662.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/28662.html</trackback:ping><description><![CDATA[<p>3.10Switch Statement<br>面向对象的一个最明显特征就是：少用switch或case语句。从本质上讲，switch语句的问题在于重复。通常用多态来解决Switch 语句带来的坏味道。switch语句常常根据type code进行选择，你要的是与该type&nbsp;code相关的函数或class。所以你应该使用Extract Method将switch语句提炼到一个独立的函数中，再以Move Method将他搬移到需要多态的那个class里头。此时你必须决定是否使用Replace Type Code with Subclass或Replace Type Code with State/Strategy。一旦这样完成继承结构之后，你就可以Replace Conditional with Polymorphism了。<br>如果你只是在单一函数中有些选择事例，而你并不想改动它们，那么&#8220;多态&#8221;就有点杀鸡用牛刀了。这种情况下Replace Parameter with Explicit Method是个不错的选择。如果你的选择条件之一是null,可以试试Introduce Null Object。<br>3.11Parallel Inheritance Hierarchies(平行继承关系)<br>在这种情况下，每当你为某个class增加一个subclass，必须也为另外一个class相应增加一个subclass。如果你发现某个继承体系的class名称前缀和另一个继承体系的class名称前缀完全相同，便是闻到了这种坏味道。消除这种重复性的一般策略是：让一个继承体系的实体(instance)指涉(参考、引用、refer to)另一个继承体系的实体。如果再接再厉运用Move Method和Move Field，就可以将指涉端的继承实体消弭。</p>
<p>3.12Lazy Class(冗赘类)<br>你所创建的每一个class，都得有人去理解它、维护它，这些工作都是要花钱的。如果一个class的所得不值其身价，它就应该消失。项目中经常会出现这样的情况：某个class原本对得起自己的身价，但重构使它身形缩水，不再做那么多工作；或开发者事前规划了某些变化，并添加一个class来对付这些变化，但变化实际上没有发生。如果某些subclass没有做满足够工作，试试Collapse Hierarchy。对于几乎没用的组件，你应该以inline class对付它们。<br>Collapse Hierarchy(折叠继承体系)<br>superclass和subclass之间无太大区别。<br>将它们合为一体。<br>动机<br>如果你曾经写过继承体系，你就会知道，继承体系很容易变得过分复杂。所谓重构继承体系，往往是将函数和值域在体系中上下移动。完成这些动作后，你很可能发现某个subclass并未带来该有的价值，因此需要把classes合并(折叠)起来。<br>作法：<br>选择你想移除的class：是superclass还是subclass?<br>使用pull up Field和pull up method或者push down method和push down field，把想要移除的class内的所有行为和数据搬移到另一个class。<br>每次移动后，编译并测试。<br>调整&#8220;即将被移除的那个class&#8221;的所有引用点，令它们改而引用合并（折叠）后留下的class。这个动作将会影响到变量的声明、参数的型别以及构造函数。<br>移除我们的目标；此时它应该已经成为一个空类。<br>编译、测试。</p>
<p>3.13Speculative Generality(夸夸其谈未来性)<br>如果所有的装置都会被用到，那就值得处理这些非必要的事情；如果用不到就不值得。用不上的装置只会挡你的路，所以，把它搬开吧。<br>如果函数或class的唯一用户是test cases(测试用例)，这就飘出了坏味道。如果你发现这样的函数或class，请把它们连同其test case都删掉。但如果他们的用途是帮助test cases检测正当功能，当然必须刀下留人。<br>3.14Temporary Field(令人迷惑的暂时值域)<br>有时你会看到这样的对象：其内某个instance变量仅为某种特定情势而设。这样的代码让人不易理解，因为你通常认为对象在所有时候都需要它的所有变量。在变量未被使用的情况下猜测起当初设置的目的，会让你发疯。<br>请使用Extract Class给这个可怜的孤儿创造一个家，然后把所有和这个变量相关的代码都放进这个新家。<br>如果class中有一个复杂算法，需要好几个变量，往往就可能导致这种坏味道。由于实现者不希望传递一长串参数，所以他把这些参数都放进值域中，但是这些值域只在使用该算法的时候才有效，其他情况下只会让人迷惑。这个时候可以用Extract&nbsp;Class把这些变量和其相关的函数提炼到一个独立的class中，提炼后的新对象是一个method object。<br>3.15Message Chains(过渡耦合的消息链)<br>用户索求对象，然后向求得的对象继续索求对象。<br>这时候应该使用Hide Delegate。应该先观察Message&nbsp;Chain最终得到的对象是用来干什么的，看看能否以Extract Method把使用该对象的代码提炼到一个独立函数中，再运用Move Method把这个函数推入Message Chain。<br>Hide Delegate(隐藏委托关系)<br><img height=305 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/refactoring5.JPG" width=425 border=0><br>&nbsp;当类图如上所示时，客户端如果想要获得对应Person的Manager，需要如下过程：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">Department&nbsp;department&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;person.Department;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Manager&nbsp;manager&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;department.Manager;</span></div>
<p>通过重构，为类Person添加属性Manager，如：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Person<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;Department&nbsp;_department;<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Department&nbsp;Department<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_department;<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_department&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Manager&nbsp;Manger<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_department.Manager;<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p>这样客户端可以这样写：<br>Manager manager = person.Manger;<br>当然如果person不属于任何一个部门，那么程序就会出错。这里其实可以引入Null Object来解决问题。</p>
<p>3.16Middle Man（中间转手人）<br>人们可能会过渡运用delegation。你也许会看到某个class所实现的接口有一半的函数都委托给其他class，这样就使过渡运用。这时你应该使用Remove Middle Man，直接和职责对象打交道。如果这样&#8220;不干实事&#8221;的函数只有少数几个，可以运用inline Method把它们放进调用端。如果这些Middle Man 还有其他的行为，你可以运用Replace Delegation with Inheritance把它们变成实责对象的subclass，这样你既可以扩展原对象的行为，又不必负担那么多的委托动作。<br>Remove Middle Man<br>这个重构过程和Hide Delegate刚好相反。<br>Replace Delegation with Inheritance</p>
这个重构过程就是把关联关系转换为继承关系。<br>即<br><img height=181 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/refactoring6.JPG" width=403 border=0><br>转变为<br><img height=177 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/refactoring7.JPG" width=403 border=0><br>3.17Inappropriate Intimacy<br>当两个类彼此关系紧密地时候，有可能是他们所包含的方法或值域处在错误的类中而导致，此时应当通过Move Method或Move Field把它们移动到合适的位置。应当看一下两个类之间是否真的需要双向导航关系，如果不是，让它们之间的关系变为单向导航关系。或者通过Extract Class把共同的函数或值域抽取出来，让每一个Class直接去调用被抽取出来的类。另外如果是子类和父类过分耦合，则可以通过将继承转换为关联的手段来降低耦合性。<br>3.18Alternative Classes with Different Interfaces（异曲同工的类）<br>如果两个函数做同一件事，却有着不同的签名式，应当运用Rename Method根据它们的用途重新命名。请反复运用Move Method将某些行为移入classes，直到两者的协议一致为止。或许可以使用Extract Superclass来解决问题。<br>3.19Incomplete Library Class（不完美的程序库类）<br>当你面对的程序类库不够好( 或者不能满足要求）而你又不能直接改变它时，可以采用Introduce Foreign Method 方法来修改其中一两个函数，或者使用Introduce Local Extension来添加行为。<br>Introduce Foreign Method (162)<br>在client class建立一个函数，并以一个server class实体作为第一个参数。书中的例子：<br><img height=288 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/refactoring8.JPG" width=693 border=0><br>Introduce Local Extension(164)<br>这种重构方式实际上就是从已封装的类库中继承你认为功能不足的那个类，然后添加你想要实现的功能。当然，有时候你想扩展的那个类碰巧加上了关键字final(java) 或sealed(c#)，这样就没办法了。<br>3.20Data Class(纯稚的数据类)<br>所谓Data Class是指：它们拥有一些值域，以及用于访问这些值域的函数，除此之外一无长物。早期的Data Class可能会包含public值域或容器类值域，应当首先将它们封装起来（用属性或特定方法）。尽量可能的把外界操纵这些值域的方法搬移到类里面来，那些不应该被其他classes修改的值域，请运用Remove Setting Method。<br>Remove Setting Method<br>即去调设值函数或属性中的set让它变为只读。<br>3.21Refused Bequest<br>当子类不愿意继承父类的某些东西时，建议将继承修改为关联。不建议随便修改继承体系。这是一种很淡的坏味道。<br>3.22Comments(过多的注释)<br>注释本身并不是坏味道，它可以帮助我们找到代码中的坏味道。<br>如果你需要注释来解释一块代码做了什么，试试Extract Method；如果method已经提炼出来，但还是需要注释来解释其行为，试试Rename Mehtod；如果你需要注释说明某系系统的需求规格，试试Introduce Assertion。<br>当你感觉需要撰写注释，请先尝试重构，试着让所有注释都变得多余。<br>如果你不知道该做什么，这才是注释的良好运用时机。除了用来记述将来的打算之外，注视还可以用来标注你并无十足把握的区域。你可以在注释里写下&#8220;为什么做某某事&#8221;。这类信息可以帮助将来的修改者，尤其是那些健忘的家伙。<br>Introduce Assertion<br>引入断言。<br>某一段代码需要对程序状态作出某种假设。注意，你可以创建自己的断言，而不仅仅是依赖已有断言。<br>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/28662.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-07-30 22:11 <a href="http://www.cppblog.com/qzb2006e/archive/2007/07/30/28662.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔记 第三章(5)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/07/17/28155.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Tue, 17 Jul 2007 13:26:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/07/17/28155.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/28155.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/07/17/28155.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/28155.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/28155.html</trackback:ping><description><![CDATA[<p><strong>3.5 Divergent Change (&nbsp;发散式变化)</strong><br>针对某一外界变化的所有相应修改，都只应该发生在单一class中，而这个新class内的所有内容都应该反映外界变化。为此，你应该找出因为某特定原因而造成的所有变化，然后运用Extract Class将他们提炼到另一个class中。<br><strong>3.6Shotgun Surgery(散弹式修改)</strong><br>如果每遇到某种变化，你都必须在许多不同的classes内作出许多小修改以响应之，你所面临的坏味道就是散弹式修改。<br>这种情况下，你应该使用Move Method和Move Field把所有需要修改的代码放进同一个class。如果眼下没有合适的class可以安置这些代码，就创造一个。通常你可以运用Inline Class把一系列相关行为放进同一个class。这可能会造成少量发散式变化，但你可以轻易处理它。</p>
<p><strong>InLine Class</strong></p>
<p>场景：你的某个class没有做太多事情(没有承担足够责任)。<br>将class的所有特性搬移到另一个class中，然后移除原class。<br>作法<br>在移动的目的class身上声明所有被移动的class的公共属性和方法。(如果&#8220;以一个独立接口表示source class函数&#8221;更合适的话，就应该在inlining之前使用Extract Interface)<br>修改所有source class引用点，改而引用吸收被移动的class的目标class。(将source class声明为private，以斩断package之外的所有引用可能。同时并修改source class的名称，这便可以使编译器帮助你捕获到所有对于source class的dangling reference(虚悬引用点)<br>编译，测试<br>运用Move Method和Move Field，将source class的特性全部搬移到目标class。<br><strong>3.7Feature Envy(依恋情结)</strong><br>有一种经典的气味是：函数对某个class的兴趣高过对自己所处之host class的兴趣。这种倾慕之情最通常的焦点便是数据。无数次经验里，我们看到某个函数为了计算某值，从另一个对象那儿调用几乎半打的取值函数。疗法显而易见：把这个函数移至另一个地点。你应该使用Move Method，把它移到它该去的地方。有时候函数只有一部分受这种依恋之苦，这时候你应该使用Extract Method把这一部分提炼到独立的函数中，再使用Move Method带它去它的梦中家园。<br>往往一个函数会用上数个classes特性。那么它究竟该被置于何处呢？我们的原则是：判断哪个class拥有最多&#8220;被此函数使用&#8221;的数据，然后就把这个函数和那些数据摆在一起。如果先以Extract Method将这个函数分解为数个较小函数并分别放置于不同地点，上述步骤也就比较容易完成了。<br><strong>3.8Data Clumps(数据泥团)<br></strong>将&#8220;总是绑在一起出现的数据&#8221;放进属于它们自己的对象中。首先找出这些数据的值域形式出现点，运用Extract Class将它们提炼到一个独立的对象中。然后运用Introduce Parameter Object 或 Preserve Whole Object为参数过长的成员函数减肥。<br>一个好的评判数据泥团的办法：删除掉众多数据中的一笔。其他数据如果不再有意义，这就是个明确的信号：你应该为它们产生一个新对象。</p>
<p><strong>3.9Primitive Obsession(基本型别偏执)</strong><br>对象技术的新手通常不愿意在小任务上运用小对象--像是结合数值和币值的money class、含一个起始值和一个结束值得range class、电话号码或邮政编码(ZIP)等等的特殊strings。你可以运用Replace Data Value with Object将原本单独存在的数值替换为对象。如果欲替换之数值是type code（型别码)，而它不影响行为，你可以运用Replace Type Code with Class将它换掉。如果你有相依于此type code的条件式，可运用Replace Type Code with SubClass或Replace Type Code with State/Strategy 加以处理。<br>如果你有一组应该总是放在一起的值域，可运用Extract Class。如果你在参数列中看到基本型数据，不妨试试Introduce Parameter Object。如果你发现自己正在从array中挑选数据，可运用Replace Array with Object。<br><strong>Replace Type Code with Class</strong><br>在以C为基础的编程语言中，type code(型别码)或枚举值很常见。如果带着一个有意义的符号名，type code的可读性还是不错的。问题在于，符号名终究只是个别名，编译器看见的、进行型别检验的，还是背后那个数值。任何接受type code作为引数(argument)的函数，所期望的实际上是一个数值，无法强制使用符号名。这会大大降低代码的可读性，从而成为臭虫之源。<br>如果把那样的数值转换为一个class，编译器就可以对这个class进行型别检验。只要为这个class提供factory method，你就可以始终保证只有合法的实体才会被创建出来，而且它们都回被传递给正确的宿主对象。<br>但是如果枚举被switch所使用，你就不能简单地将它替换为class。因为switch往往只会接受整型数据。所以应该首先对switch运用Replace Conditional with Polymorphism重构，而在这之前，还要进行Replace Type Code with Subclasses或Replace Type Code with State/Strategy把type code处理掉。<br>作法：<br>1、为 type code建立一个class。其中包含相应的用于记录type code的值域，并准备一组static变量保存允许被创建的实体，并以一个static函数根据原本的type code 返回合适的实体。<br>2、修改source class代码，让他使用上述新建的class。<br>3、编译、测试<br>4、对于source class中每一个使用type code 的函数，相应建立一个函数，让新函数使用新的class。你需要建立&#8220;以新class实体为自变量&#8221;的函数，用以替换原先&#8220;直接以type code为引数&#8221;的函数。你还需要建立一个&#8220;返回新class实体&#8221;的函数，用以替换原先一直返回type code的函数。建立新函数前，你可以使用Rename Method修改原函数名称，明确指出那些函数仍然使用旧式的type code。<br>5、逐一修改source class用户，让它们使用新接口。<br>6、每修改一个用户，编译并测试。<br>7、删除使用&#8220;type code&#8221;的接口，并删除保存旧type code的静态变量。<br>8、编译测试。<br><strong>Replace Type Code with SubClass</strong><br>我的理解：<br><img height=156 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/cls_room1.JPG" width=187 border=0><br>在这里Room类包含一个属性IsMeetingRoom。如果为true，则这个房间就是一个会议室，如果为false，则这个房间就是一个普通的房间。这里true和false可以理解为一个简单的&#8220;型别编码&#8221;。它可以重构为下面的形式：<br><img height=285 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/cls_room2.JPG" width=416 border=0><br>更复杂的情况：<br><img height=158 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/cls_room3.JPG" width=172 border=0><br>这样就需要根据RoomType的实际数量分离出多个子类来。</p>
<p>作法：<br>使用Self Encapsulate Field方法把type code自我封装起来。如果type code被传递给构造函数，你就需要将构造函数换成factory method.<br>为type code的每一个数值建立一个相应的subclass。在每个subclass中覆写type code的取值函数(getter)，使其返回相应的type code值。<br>每建立一个新的subclass,编译并测试。<br>从superclass中删除掉保存type code的值域。将type code访问函数声明为抽象函数。<br>编译，测试。<br><strong>Replace Type Code with State/Strategy</strong> <br>你有一个type code，它会影响class的行为，但你无法使用subclassing。<br>以state object(专门用来描述状态的对象)取代type code。<br>之所以无法subclassing是因为Type Code会在对象生命周期过程中发生变化。<br>如果你打算再完成本项重构之后再以Replace Conditional with Polymorphism(用多态替换条件判断)简化一个算法，那么选择Strategy模式比较合适；如果你打算搬移与状态有关的数据，而且你把新建对象视为一种变迁状态，就应该使用State模式。<br><br><strong>Replace Array with Object</strong> <br>你有一个数组(array)，其中的元素各自代表不同的东西。<br>以对象替换数组，对于数组中的每个元素，以一个值域表示之。<br>String[] row =new String[3];<br>row[0]="Liverpool";<br>row[1]="15";<br>转换为<br>Performance row=new Performance();<br>row.setName("Liverpool");<br>row.setWins("15");<br>3.10Switch Statements</p>
<p>如果你只是在单一函数中有些选择事例，而你并不想改动它们，那么&#8220;多态&#8221;就有点杀鸡用牛刀了。这种情况下Replace Paremeter with Explicit Method是个不错的选择。如果你的选择条件之一是null，可以试试Introduce Null Object<br><strong>Replace Paremeter with Explicit Method</strong><br>此方法即是将包含多个switch分支的函数的各个分支独立成不同的函数。比如：<br>public static&nbsp;Object CreateObject(int typeOfObject)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch(typeOfObject)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 1:return new A();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 2:return new B();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 3:return new C();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br>转换为：<br>public static&nbsp;Object Create1()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new A();<br>}<br>public static Object Create2()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new B();<br>}<br>public static Object Create3()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new C();<br>}<br>思考：这样会削弱此函数的运行期特性。<br><strong>Introduce Null Object</strong><br>使用这种重构方法的好处就是你不用在向一个对象发送消息的时候去检验这个对象是否存在。因为对象确实存在，只不过有可能对你发送的消息做出&#8220;我是空&#8221;的回应。<br>作法<br>为source class建立一个subclass，使其行为像source class的null版本。在source class和null class中都加上IsNull()函数，前者的IsNull()应该返回false，后者的应该返回true.可以建立一个nullable接口，将isnull函数放在其中，让source class实现这个接口。<br>另外可以创建一个testing接口，专门用来检验对象是否为null.<br>编译。<br>找出所有&#8220;索求source obejct却得到一个null&#8221;的地方。修改这些地方，使他们改而获得一个null object。<br>找出所有&#8220;讲source object与null做比较的地方&#8221;。修改这些地方，使它们调用IsNull()函数。<br>你可以在不该在出现null value的地方放上一些断言，确保null的确不再出现。这可能对你有所帮助。<br>这出这样的程序点：如果对象不是null，做A动作，否则做B动作。<br>对于每一个上述地点，在null class中覆写A动作，使其行为和B动作相同。<br>使用上述的被覆写动作(A)，然后删除&#8220;对象是否等于null&#8221;的条件测试。编译并测试。<br>其他特殊情况<br>使用本项重构时，你可以有数种不同的null objects，例如你可以说&#8220;没有顾客&#8221;和&#8220;不知名顾客&#8221;这两种情况是不同的。果真如此，你可以针对不同的情况建立不同的null class。有时候null objects 也可以携带数据，例如不知名顾客的使用记录等等。<br>本质上讲，这是一个比Null Object模式更大的模式：Special Case模式。所谓Special case class是某个class的特殊情况，有着特殊的行为。因此表述不知名顾客的UnKnownCustomer 和表示没有顾客的NoCustomer都是Customer的特例。你经常可以在表示数量的class中看到这样的特例类。例如Java浮点数有&#8220;正无穷大&#8221;、&#8220;负无穷大&#8221;和&#8220;非数量&#8221;等特例。special case class的价值是：它们可以降低你的错误处理开销。例如浮点运算决不会抛出异常。如果你对NaN作浮点运算，结果也会是个NaN。这和&#8220;null object&#8221;的访问函数通常会返回另一个null object是一样的道理。</p>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/28155.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-07-17 21:26 <a href="http://www.cppblog.com/qzb2006e/archive/2007/07/17/28155.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The C++ Standard Library : A Tutoral and Reference 读书笔记之auto_ptr</title><link>http://www.cppblog.com/qzb2006e/archive/2007/07/12/27880.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Thu, 12 Jul 2007 14:46:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/07/12/27880.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/27880.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/07/12/27880.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/27880.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/27880.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这一部分会将要讨论一下auto_ptr.c++标准库提供auto_ptr作为一种智能指针,有了这种智能指针,就可以在异常被抛出的时候避免资源的泄漏.注意,auto_ptr只是智能指针的一种.因为事实上有多种智能指针存在.而auto_ptr只是被用来满足某种情形下的需求的.而对于其他一些情形,auto_ptr无能为力.所以在使用的时候 要格外注意.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: 24pt;"><span style="font-size: 18pt;"><span style="font-size: 8pt;"><span style="font-weight: bold; font-size: 12pt;">auto_ptr的动机</span></span><span style="font-weight: bold;"></span></span><span style="font-weight: bold;"></span></span><span style="font-weight: bold;"></span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通常,一个函数会按照下面的流程进行操作:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.获取资源.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.进行一些操作.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.释放之前所获取的资源.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果函数所获取的那些资源与本地对象绑定,它们就会在函数结束的时候被自动释放掉.因为本地对象的析构函数会被调用.但是如果资源被显式获取,并且没有与任何对象绑定,它们必须也被显式的释放掉.在使用指针的时候,资源通常是被显式管理的.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一种典型的像上面这样使用资源的方式就是使用new来创建和用delete来释放.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但是作释放用的delete操作往往被忽略(特别是函数有返回值的时候).当然,出现异常的时候,也同样会发生这种风险.因为异常有可能马上停止你函数的执行,而不去进行delete释放.结果就是内存泄漏,或者说得宽泛一些,是"资源泄漏".为了避免资源泄漏,通常需要函数能够捕获所有的异常.随之而来的就是,代码变得越来越复杂,冗长.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 伴随着这种情况的发生,一种智能指针auto_ptr出现了.在任何时候,一旦指针本身被销毁,它所指向的数据也会被销毁.此外,因为智能指针是一个本地变量,不管函数到底是因为正常结束,还是因为非正常结束,auto_ptr所指向的数据都会被销毁.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有了auto_ptr,delete语句和catch语句就变得不那么必要了.auto_ptr和普通指针的使用方式基本相同,即用样用"*"表示它所指向的对象,同样用"-&gt;"来访问所指向对象的成员方法.但是有关指针的运算(比如指针的自加)不被支持(这也许是一个优点,因为指针运算也许会造成一些麻烦).<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意auto_ptr&lt;&gt;不允许你使用指派的方式来声明它所指向的对象,比如: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面的操作是不允许的:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::auto_ptr&lt;ClassA&gt; ptr2 = new ClassA; //ERROR<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而应该采用显式的构造函数来初始化:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::auto_ptr&lt;ClassA&gt; ptr1(new ClassA);&nbsp; //OK<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: 12pt; font-weight: bold;">通过auto_ptr来转换所有权</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr在语意上提供了对于所有全的严格约束.这意味着因为如果一个auto_ptr删除了它所指向的对象,那么这个对象将不会被其他任何对象所拥有.两个或以上的auto_ptr绝不能同时拥有一个对象.不幸的是,这种情况是有可能出现的.所以只能有程序员来确保这种情况不会发生.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么在这种情况下,auto_ptr的拷贝构造函数如何工作呢?通常它会把一个对象的数据复制给另外一个对象,但是在这里,恰恰是这种行为会导致两个auto_ptr拥有相同对象这种情况的出现.解决方法很简单,但是却得出了一个重要结论:auto_ptr的拷贝构造函数和指派操作促成了auto_ptr对于对象所有权的一次移交.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 看一下下面的代码:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //initialize an auto_ptr with a new object<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::auto_ptr&lt;ClassA&gt; ptr1(new ClassA);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //copy the auto_ptr<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //- transfers ownership from ptr1 to ptr2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::auto_ptr&lt;ClassA&gt; ptr2(ptr1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一句中,ptr1拥有new所创建的那个对象.然后第二句把对于对象的所有权从ptr1转移给了ptr2.所以在第二句之后,ptr2拥有new创建的那个对象的所有权,而ptr1则自动失去了对于那个对象的所有权.ClassA只会在ptr2被析构的时候被释放掉.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同样,对于一次指派操作也是如此.如下所示:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //initialize an auto_ptr with a new object<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::auto_ptr&lt;ClassA&gt; ptr1(new ClassA);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::auto_ptr&lt;ClassA&gt; ptr2; //create another auto_ptr<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ptr2 = ptr1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //assign the auto_ptr<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //- transfers ownership from ptr1 to ptr2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意,随着所有权的移交,之前失去对象所有权的那个auto_ptr就变成了一个空指针.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然,还可以让这个失去所指的空指针重新指向一个对象,像下面这样:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::auto_ptr&lt;ClassA&gt; ptr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //create an auto_ptr<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ptr = std::auto_ptr&lt;ClassA&gt;(new ClassA); //OK, delete old object and own new<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;  对于所指向的对象的所有权的变换为我们提供了auto_ptr的一种潜在用法.函数可以使用向其他的函数传递所有权.这包含两种情况.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.传入函数的对象不再使用.即在auto_ptr作为参数传递的时候.在这种情况下,被调用的函数得到了传入的auto_ptr所指向的那个对象的所有权.因此,如果函数不再将对象的所有权转移出来,那么对象就会在函数的调用结束之后销毁.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.函数要向外传出对象.当auto_ptr被返回的时候,所有权由被调用的函数转移给调用方.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于auto_ptr总是牵扯到对象所有权变换的问题,所以在使用的时候一定要注意你是否真的要转换这个所有权.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 你可能打算通过引用传递auto_ptr(s).但是这样做有可能最终你都不清楚所有权的归属了.总之,这不是一个好的决定或设计.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从auto_ptr的概念出发,你可能会觉得即使是传递常指针的话,对象的归属也会改变.如果这种情况可能发生,那将是非常危险的.因为人们总是不期待一个成为"常量"的东西发生改变.幸运的是,通过一些技术上的处理,这样做是不可能的.如:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">iostream</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;std;<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;getValue(auto_ptr</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">);<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-weight: bold;">const</span><span style="color: #000000; font-weight: bold;">&nbsp;auto_ptr&lt;</span><span style="color: #0000ff; font-weight: bold;">int</span><span style="color: #000000; font-weight: bold;">&gt;&nbsp;myAutoPtr=auto_ptr&lt;</span><span style="color: #0000ff; font-weight: bold;">int</span><span style="color: #000000; font-weight: bold;">&gt;(</span><span style="color: #0000ff; font-weight: bold;">new</span><span style="color: #000000; font-weight: bold;">&nbsp;</span><span style="color: #0000ff; font-weight: bold;">int</span><span style="color: #000000;"><span style="font-weight: bold;">);</span><br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">myAutoPtr</span><span style="color: #000000;">=</span><span style="color: #000000;">10</span><span style="color: #000000;">;<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000; font-weight: bold;">getValue(myAutoPtr)</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">endl;<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;getValue(auto_ptr</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;ptr)<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">*</span><span style="color: #000000;">(</span><span style="color: #000000;">*</span><span style="color: #000000;">ptr);<br></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">}</span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面首先定义了常量的auto_ptr,这就表明,这个auto_ptr不能将自己所指对象的所有权传递给其他对象.因而调用函数getValue的时候如果传递了上面定义的auto_ptr,就会被编译器发现,并作为编译错误反馈回来:<br>错误： passing &#8216;const std::auto_ptr&lt;int&gt;&#8217; as &#8216;this&#8217; argument of &#8216;std::auto_ptr&lt;_Tp&gt;::operator std::auto_ptr_ref&lt;_Tp1&gt;() [with _Tp1 = int, _Tp = int]&#8217; discards qualifiers<br>将auto_ptr(s)作为成员变量<br>当然,如果在类中使用auto_ptr的时候,你同样也可以避免资源泄漏这种问题的发生.如果你使用auto_ptr取代通常的指针的话,你将不再需要对那些对象进行手动的析构处理.同时,auto_ptr也能够有效避免因为初始化异常而导致资源泄漏这种情况的发生.因为析构总是在构造之后,所以如果在构造的时候发生异常,你往往不能够及时释放资源,进而导致资源泄漏情况的发生.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但是,在享用了auto_ptr带来的诸多好处的同时,你在处理拷贝构造函数和重载赋值操作的时候,要格外注意auto_ptr所有权变换的问题.当然,避免这类问题的最好方法就是使用常量指针.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: 12pt;"><span style="font-weight: bold;">有关auto_ptr(s)的滥用</span></span><span style="font-weight: bold;"></span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr能够满足一些需要,特别是容易发生资源泄漏的时候,它总能够发挥好的效果.但是在使用它的时候仍然需要注意,不要滥用.在使用的时候,要注意以下几点:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.auto_ptr(s)不能够共享对于所指向对象的所有权.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2auto_ptr(s)不提供对于数组的支持.因为在释放资源的时候,auto_ptr使用的是delete而不是delete[].当然,对于数组而言,STL也有相应的处理办法,比如容器.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.auto_ptr(s)不是智能指针的全部.注意它并不能解决一切问题.注意它的应用场景.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.auto_ptr(s)不能满足容器中对象的操作要求.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
<br>
<br><br>
<br><br><br>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>    <img src ="http://www.cppblog.com/qzb2006e/aggbug/27880.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-07-12 22:46 <a href="http://www.cppblog.com/qzb2006e/archive/2007/07/12/27880.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔记 第三章(4)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/07/10/27833.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Tue, 10 Jul 2007 14:16:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/07/10/27833.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/27833.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/07/10/27833.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/27833.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/27833.html</trackback:ping><description><![CDATA[<p>现在回到重构--改善既有代码的设计这本书。<br>3.4Long Parameter List（过长参数列）<br>如果&#8220;向既有对象发出一条请求&#8221;就可以取得原本位于参数列上的一份数据，那么你应该激活重构准则Replace Parameter with Method。上述的既有对象可能是函数所属class内的一个值域，也可能是另一个参数。你还可以用 Preserve Whole Object将来自同一对象的一堆数据收藏起来，并以该对象替换它们。如果某些数据缺乏合理的对象归属，可使用Introduce Parameter Object为它们制造出一个&#8220;参数对象&#8221;。</p>
<p>Replace Parameter with Methods(以函数取代参数)<br>对象调用某个函数，并将结果作为参数，传递给另外一个函数。而接受该参数的函数也可以（也有能力）调用前一个函数。<br>动机<br>如果函数可以通过其它途径（而非参数列）获得参数值，那么它就不应该通过参数取得该值。<br>缩减参数列的办法之一就是，看看&#8220;参数接受端&#8221;是否可以通过&#8220;与调用端相同的计算&#8221;来取得参数携带值。如果调用端通过&#8220;其所属对象内部的另一个函数&#8221;来计算参数，并在计算过程中&#8220;未曾饮用调用端的其它参数&#8221;，那么你就应该将这个计算过程转移到被调用端内，从而除去该项参数。如果你所调用的函数隶属另一对象，而该对象拥有一个reference指向调用端所属对象，前面所说的这些也同样适用。<br>作法<br>1、如果有必要，将参数的计算过程提炼到一个独立函数中。<br>2、将函数本体内&#8220;对该参数的引用&#8221;替换为对&#8220;新函数的引用&#8221;。<br>3、每次替换后，修改并测试。<br>4、全部替换完成后，适用Remove Parameter将该参数去掉。</p>
<p>
<hr>
<p>思考：<br>确实从实践角度讲，上面这种方法是一种很实用的重构方法。确实是缩减了函数的参数个数，并隐藏了一些中间结果。但是我认为，在应用这个方法的时候，还应当考虑这样两个问题：<br>1、当中间函数（方法）被隐藏的时候，以这个中间函数的返回值为参数的那个函数名还能够表述自己的用途吗？<br>2、被修改的那个函数所处的具体语境是什么。因为在面向对象编程的时代，单独去考虑一个函数的情况是很少的。确保这个函数是否处在正确的位置上（如是否处在正确的类中）是必要的。<br>
<hr>
<br>此间存在一个重要的例外。有时候你明显不希望造成&#8220;被调用之对象&#8221;与&#8220;较大对象&#8221;间的某种依存关系。这时候将数据从对象拆解出来单独作为参数，也很合情合理。但是请注意其所引发的代价。如果参数列太长或变化太频繁，你就需要重新考虑自己的依存结构了。
<p>&nbsp;Introduce Parameter Object（引入参数对象）<br>某些参数总是很自然的同时出现，以一个对象取代这些参数。<br>你常会看到特定的一组参数总是一起被传递。可能有好几个函数都使用这一组参数，这些函数可能隶属同一个class，也可能隶属不同的classes。这样一组参数就是所谓的Data Clump(数据泥团)。我们可以运用一个对象包装所有这些数据，再以该对象取代它们。<br>作法：<br>1、新建一个class，用以表现你想替换的一组参数。将这个class设为不可变的(不可被修改的，immutable)。<br>2、编译。<br>3、针对使用该组参数的所有函数，实施Add Parameter，以上述新建class之实体对象作为新添参数，并将此一参数值设为null。<br>4、对于Data Clump(数据泥团)中的每一项(在此均为参数)，从函数签名式中移除之，并修改调用端和函数本体，令他们都改而通过&#8220;新建的参数对象&#8221; 取得该值。<br>5、每除去一个参数，编译并测试。<br>6、将原先的参数全部除去之后，观察有无适当函数可以运用Move Method搬移到参数对象中。</p>
<hr>
思考：<br>现在我有一个函数f，函数定义如下：<br>public string f(int i,int j,string s)<br>{<br>&nbsp;&nbsp;&nbsp;int newValue=i+j;<br>&nbsp;&nbsp;&nbsp;string result=s+":"+newValue.ToString();<br>&nbsp;&nbsp;&nbsp;return result;<br>}<br>现在我把这三个参数转化为类对象，类名定义为MyParameter<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyParameter<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_i;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;I<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_i;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;{&nbsp;_i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_j;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;J<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_j;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;{&nbsp;_j&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;_s;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;S<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">&nbsp;{&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_s;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">&nbsp;{&nbsp;_s&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;value;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;MyParameter(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;j,&nbsp;stirng&nbsp;s)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;i;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_j&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;j;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_s&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;s;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p>然后再我的代码中这样写：<br>f(new MyParameter(3,2,"Result"));</p>
<p>发现什么问题了吗？<br>1、好像参数并没有减少，只不过是移动到了构造函数中；<br>2、你从f参数中将会看不出f中到底需要什么东西（如果参数名称体现了参数的用途的话）。<br>这说明：<br>1、虽然这是经典的重构方法，但是不能滥用，在使用的时候要谨慎考虑场景是否合适。<br>2、注意TDA原理，不要刻意产生太多的中间对象。<br>3、参数不能随便合并或隐去，要特别注意领域模型，要切合领域模型所表述的意图。<br>我个人认为可以应用的场景：<br>就是文中所说的DataRange，即适合于被转换为参数对象的参数列具有通用的含义，并且概念层次比较低。</p>
<p>
<hr>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/27833.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-07-10 22:16 <a href="http://www.cppblog.com/qzb2006e/archive/2007/07/10/27833.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔记 第三章(3)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/07/08/27579.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sun, 08 Jul 2007 12:31:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/07/08/27579.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/27579.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/07/08/27579.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/27579.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/27579.html</trackback:ping><description><![CDATA[<p>其实在看Martin Fowler的重构这本书的很长一段时间里，我一直把它错当成了另外一本书的中文版，那本书的名字就是：John.Wiley.and.Sons.Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully.Jun.2006<br>以前曾经看过这本书，目前还没有找到中文版。相对于《重构--改善既有代码的设计》的侧重实践来说，上面这本书理论性更强一些。看讲实践的书有个缺点，就是你看了不上手做一做的话，等于白看，而理论呢，你可以记住。所以下面穿插一些《Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully》的理论，有很多通过英文字面意思很难理解，这样我会在网上找些资料，然后抄记在下面：<br><strong>设计原理<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正如代码会&#8220;有味&#8221;一样，结构也会&#8220;有味&#8221;，他们通常会由对于设计原理的违反而引起。因此设计原理会为我们提供一些有价值的东西进而帮助我们为设计去去狐臭。在我们从设计中找出违反这些设计原理的地方的同时,我们也有了自己的想法来改善我们的设计。。下表列出了当前流行的设计原理：<br></strong></p>
<p>1、<span style="BACKGROUND-COLOR: yellow">DRY</span>(Don't Repeat Yourself)：不要写重复的代码。也可以叫做&#8220;一次且仅一次(Once and Only Once)&#8221;原理。<br>2、<span style="BACKGROUND-COLOR: yellow">SCP</span>(Speaking Code Principle)：代码应该清楚地表明它自己的意图。代码中出现注释，说明代码不能清楚地表现自己的意图。<br>3、<span style="BACKGROUND-COLOR: yellow">OCP</span>(Open Closed Principle)：一个设计单元应该向修改开放。这种修改不应该导致调用方无效。继承是一种能够让你达到此目的的方法。子类可以进行一些调整，而超类保持不变。<br>4、<span style="BACKGROUND-COLOR: yellow">LSP</span>(Liskov Substitution Principle)：个软件实体如果使用的是一个基类的话，那么一定适用于其子类，而且它根本不能察觉出基类对象和子类对象的区别。反过来代换是不成立的<br>5、<span style="BACKGROUND-COLOR: yellow">DIP</span>(Dependency Inversion Principle)：等级高的概念不应该依赖于等级低的概念（或实现）。对于从属关系来说刚好相反。因为等级高的概念比起等级低的概念来说变动的可能性要小。<br>6、<span style="BACKGROUND-COLOR: yellow">ISP</span>(Interface Segregation Principle)：接口隔离原理。接口应该尽量的小。他们应该仅包含很少的方法，但是这些被放置在同一个接口中的方法应该是紧密相关的。<br>7、<span style="BACKGROUND-COLOR: yellow">REP</span>(Reuse/Release Equivalency Principle)：可重用的元素必然是已经被发布的元素。</p>
8、<span style="BACKGROUND-COLOR: yellow">CRP</span>(Common Closure Principle)：<font style="FONT-SIZE: 12pt" size=2>包中的所有类对于同一类性质的变化应该是共同封闭的。</font> 一个变化若对一个包产生影响，则将对该报的所有类产生影响。而对其他的包不构成任何影响。<br>9、<span style="BACKGROUND-COLOR: yellow">ADP</span>（Acyclic（无环的）Dependencies Principle）：包之间的依赖关系应当是无环的。<br>10、<span style="BACKGROUND-COLOR: yellow">SDP</span>(Stable Dependencies Principle)：一个包应该依赖于至少像它自己那样稳定的包。<br>11、<span style="BACKGROUND-COLOR: yellow">SAP</span>（Stable Abstractions Principle）：越稳定的包，其抽象程度越高。不稳定的包通常是具体化的包。<br>12、<span style="BACKGROUND-COLOR: yellow">TDA</span>（Tell,Don't Ask）：不要向一个对象去申请另外一个对象，而应该告诉这个对象应该如何去做。<br>13、<span style="BACKGROUND-COLOR: yellow">SOC</span>(Separation Of Concerns)：不要在一个类中包含多个关注点。这通常也被叫做&#8220;责任单一原理&#8221;。<br><strong>类关系图中的&#8220;狐臭&#8221;</strong><br>两个或多个类之间的关系通常包含&#8220;使用&#8221;和&#8220;继承&#8221;两种。如果我们想在一个系统中找出&#8220;使用&#8221;关系，我们应该看一下&#8220;静态&#8221;关系图。在系统运行时呈现出来的&#8220;使用&#8221;关系构成了对象之间的动态关系图。<br><strong>一、无用类<br></strong><img style="WIDTH: 568px; HEIGHT: 224px" height=224 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/refactoring2.JPG" width=568 border=0><br><strong>出自Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully</strong><br>那些不再使用的类会因为具有一些显而易见的无用功能而增加系统的负担。这些负担包括：程序开发者需要花费大量的时间来分辨出一个正确的类，构建系统的时间变得更长，系统变得更加难以理解。<br>相对于完全无用的类，更多的情况下你会遇到包含部分无用代码的类。这是因为一个类中包含了太多的功能，而在真正使用的时候，那些功能又被抛弃掉了。我们可以在重构的时候依据这些功能把类进行拆分，通过拆分我们会首先得到无用类。然后进一步对它进行处理。<br>不仅仅单单一个类会成为无用类，有的时候，处在同一个关系图中的类都回成为无用类(s)。<br>无用类通常因为两种原因而出现：<br>１、技术上提供覆盖面尽可能广的支持：一个开发者推测一个类可能最终会被用到，即使没有迹象表明现实中有与之对应的需求。<br>２、重构：通过对系统的修改，以前需要用到的类，现在变得陈旧过期了。<br><strong>二、树型依赖关系<br></strong><img style="WIDTH: 628px; HEIGHT: 244px" height=244 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/refactoring3.JPG" width=628 border=0><br><strong>出自Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully</strong><br>树型依赖关系图体现了对于系统的一种分解。树中的每一个类都确定的被另外一个类使用。<br>鉴于在面向对象的应用程序中，功能分解本身通常会被看作是一种&#8220;狐臭&#8221;，一种树型依赖结构像重复代码一样也应该被看作是一种&#8220;狐臭&#8221;。在图3-6中，类Protocol除了被类Data Storage使用外，不再被别的地方使用。重用没有发生。<br><strong>三、静态环状依赖关系<br></strong><img style="WIDTH: 535px; HEIGHT: 198px" height=198 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/refactoring4.JPG" width=535 border=0><br><strong>出自Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully</strong><br>两个类彼此使用对方是最简单的环状依赖关系。环状依赖关系中也可以包含多个类。<br>环状依赖关系会使环本身变得更加臃肿。环所具有的消极影响包括：<br>a、不可理解性：这些类不能够被一个又一个的单独理解，因为它们彼此依靠对方来实现功能。又或者是，一个类需要从多个类中选择一个作为理解他们本身的前提。<br>b、可维护性：环状依赖可能包含严重的并且不可预测的递推关系，进而导致修改包含它的系统变得非常困难。<br>c、可计划性：对环的修改到底会造成什么影响是很难预期的。估算到底需要多少的工作来完成这个修改会是一件很困难的事。<br>d、设计的清洁性：因为处在环中的那些类会直接或间接的访问到处在环中的任意一个类，因此，从理论上讲，类中的这种关系太随意了。如果在这个环中又恰好把一个方法放到错误的类中，会导致理解这种设计变得更加困难。<br>e、重用性：这些类必须同时重用。如果在一个给定的语境中，只有其中的一个类所提供的功能被关注，因为处在环中，这个类不能被简单的剥离并使用。<br>f、可测试性：这些类必须一起被测试。这增加了测试的要求以及堪错的难度。如果想要独立的测试其中的一个类，就必须使用&#8220;伪对象&#8221;。<br>g、异常处理：通常异常会在环中被&#8220;堆积&#8221;。如果环中的一个方法抛出了异常，他会潜在得影响环中的其他方法。<br>h、依赖引入问题：每一个处于环中的类同时又依赖于另一个处于环中的类处在环外的依赖关系。<br>显然，环中的最大长度越大，代码的&#8220;狐臭&#8221;味就越浓。然而，在有些地方，只包含两个类的环却是一种被推崇的设计方案，被应用于很多设计模式中（如迭代器模式）。<br><strong>四、显式依赖<br></strong>面向对象支持封装原理以及信息隐藏原理：内部的实现被隐藏于接口之中。客户端的代码无须知道任何有关于API的实现。另外，接口与实现类之间存在一些&#8220;裂痕&#8221;。很多开发者相信封装和信息隐藏只会在成员变量被定义为&#8220;私有&#8221;的时候才会有效。这当然不是事实：在很多系统中都是支持&#8220;属性&#8221;的，并且属性可以被继承。然而，有这样一个事实，在一个系统中，显式依赖关系却是无法隐藏的。一个具有公共依赖关系的系统在被修改的时候，总会产生这样那样的问题，反之，私有的局部的依赖关系只会有小范围的影响。<br>TDA(Tell,don't ask)原理指出了一条正确的途径：理想情况下，客户端告诉对象自己打算做什么。既不要通过已有对象获取一个新的对象，更不要用那个新的对象进行一些操作。<br>下面看一个例子。在这个例子中，&#8220;订单&#8221;有很多的状态。我们可以简单的以打开的订单和关闭的订单来简单的区分一下。打开的订单就是客户未回款的订单。现在我们要写一些代码，来计算所有打开的订单的总额。<br>如果我们使用一个方法calculateValueOpenOrders(注意，这个方法是写在调用方的，我们的调用方的类名定为Foo），而方法体如下。可以看出这个方法违反了TDA原理：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">&nbsp;calculateValueOpenOrders(ListOfOrders&nbsp;orders)&nbsp;<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">&nbsp;totalValue&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0.0f</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">orders.getNumber();&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Order&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;orders.getOrder(i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(a.isOpen)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;totalValue&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;a.getValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;totalValue;<br>}</span></div>
原因就是客户端的Foo直接使用Orders来获取其中的一些信息，而不是告诉Orders我要做什么。<br><img style="WIDTH: 590px; HEIGHT: 242px" height=242 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/refactoring1.JPG" width=590 border=0><br><strong>出自Refactoring.in.Large.Software.Projects.Performing.Complex.Restructurings.Successfully</strong><br>现在我们做一下修改，把打开的订单的金额计算移动到订单内部进行。如果订单是打开的，返回本订单的金额，反之，返回0。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ListOfOrders&nbsp;<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">&nbsp;calculateValueOpenOrders()&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">&nbsp;totalValue&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0.0f</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">getNumber();&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Order&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;getOrder(i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;totalValue&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;a.getOpenValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;totalValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Order&nbsp;<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">&nbsp;getOpenValue()&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(isOpen())&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;getValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
我们可能会因为所有Order都要返回打开的订单的金额而感觉不爽。如果你打算多次使用TDA原理，你可能通过增加一个方法&#8220;addOpenValue&#8221;来增加类order的柔性。但是，同时这也意味着类Order会知道另外的一些Order的存在。在这种情况下，我们可能会违反SOC（即单一职责原理）。我们不应该忽略这样一点：在使用一些设计原理的时候，还要兼顾系统的平衡性。在这个例子中，这个方法是否应该加入取决于它是否真的与这个类的&#8220;领域模型&#8221;所匹配。<br>新的实现方式不仅仅使代码更加简短，而且还包括如下的优点：<br>功能有了正确的归属。在大多数情况下，上面第一段代码中的方法calculateValueOpenOrders通常是被放到UI类中或者是一些Helper类中，而这些类通常有一些奇异的名字（比如OpenOrders Calculator）。这对于这个方法来说，不是一个正确的归属。<br>TDA原理确保类的使用应该局部化，而不要散步到系统的各个角落。因此可以简化一些优化方案的实现。<br>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/27579.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-07-08 20:31 <a href="http://www.cppblog.com/qzb2006e/archive/2007/07/08/27579.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The C++ Standard Library : A Tutoral and Reference 读书笔记之错误和异常处理</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/26/26943.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Tue, 26 Jun 2007 14:18:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/26/26943.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26943.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/26/26943.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26943.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26943.html</trackback:ping><description><![CDATA[;C++标准库风格迥异.它包含了设计和实现风格各不相同的不同来源的软件.错误处理和异常处理是一个典型.标准库中的string类们支持更加细化的错误处理.它们会监测每一处有可能发生问题的地方并会在有错误的时候抛出异常.另外一些,比如STL和valarrays比较安全性而言更加注重效率.所以它们很少监测逻辑错误,并仅仅在运行时错误发生的时候才抛出异常.<br>有三种标准异常类:<br>1.语言支持型异常(Exceptions for language support
)<br>比如:<br>用new创建对象失败的时候,会抛出bad_alloc异常;<br>dynamic_cast失败会抛出bad_cast异常;<br>函数抛出不可控异常的时候会抛出bad_exception异常或调用unexpected函数.<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">iostream</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;E1<br>{<br><br>};<br></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;E2<br>{<br>};<br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;f_throwE1()&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">(E1)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;E1();<br>}<br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;f_throwE2()&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">(E1)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;E2();<br>}<br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;f_throwE2AsBadException()&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;(E1,std::bad_exception)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;E2();<br>}<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f_throwE1();&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">1:抛出可控异常</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f_throwE2();&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">2:抛出不可控异常,执行unexpected函数</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f_throwE2AsBadException();&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">3:抛出不可控异常,被认为是bad_exception</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;E1&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">e1)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">E1&nbsp;error&nbsp;occured</span><span style="color: #000000;">"</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">std::endl;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;std::bad_exception&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">e2)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">bad_exception&nbsp;occured</span><span style="color: #000000;">"</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;"></span>catch(const E2 &amp;e2)<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;std::cout&lt;&lt;"E2 error occured"&lt;&lt;std::endl;<br>&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;catch(...)<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;std::cout&lt;&lt;"unknown exception occured"&lt;&lt;std::endl;<br>&nbsp;&nbsp; &nbsp;}
<span style="color: #000000;"><br>}<br></span></div>
上面的程序中,执行1,会产生如下的结果:<br>E1 error occured<br>执行2,并没有被作为类型E2的异常所捕获.而是出现了如下提示:<br>terminate called after throwing an instance of 'E2'<br>忽略<br>现在执行3.结果并没有捕获到std::bad_exception异常.而是仍然出现了这样的错误提示:<br>terminate called after throwing an instance of 'E2'<br>忽略
<br>同样的的例子,上面是在linux下执行的情况.下面换做vs2003的vc7.执行3,结果是:<br>unknown exception occured<br>即也没有捕获到std::bad_exception,但是被更加通用的...所捕获了.这是编译器情况的不同.<br>2.c++标准库的异常(Exceptions for the C++ standard library)
<br>c++标准库的异常类通常从logic_error类继承.逻辑错误从理论上来说,至少应该被程序所避免,例如通过对于函数参数进行额外的测试.c++提供了诸如invalid_argument,length error,out_of_range,domain_error等异常类.<br>
3.在程序域之外的异常(Exceptions for errors outside the scope of a program)
<br>此类异常通常难于避免.<br>异常类的头文件<br>异常的基类和bad_exception类被定义在&lt;exception&gt;里;<br>类bad_alloc在&lt;new&gt;中被声明;<br>bad_cast和bad_typeid在&lt;typeinfo&gt;中被声明;<br>ios_base::failure在&lt;ios&gt;中被声明;<br>所有其他的类都被定义在&lt;stdexcept&gt;中.<br>异常类的成员<br>在异常类中除类型信息之外,唯一可以获取的信息来自于函数what():<br>namespace std {<br>&nbsp;&nbsp;&nbsp; class exception {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual const char* what() const throw();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>}<br><br>
使用what来获取信息:<br>try {<br>&nbsp;&nbsp;&nbsp; ...<br>}<br>catch (const exception&amp; error) {<br>&nbsp;&nbsp;&nbsp; //print implementation-defined error message<br>&nbsp;&nbsp;&nbsp; cerr &lt;&lt; error.what() &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; ...<br>}<br>可以以下面的方式创建标准异常:<br>string s;<br>...<br>throw out_of_range(s);<br><br>
或者<br>throw out_of_range("out_of_range exception (somewhere, somehow)");
<br>从标准异常类继承<br>例如:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">exception</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">iostream</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;MyException:</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;std::exception<br>{<br></span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;errorMessage;<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;MyException(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;errMsg)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;errorMessage</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">[strlen(errMsg)];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(errorMessage,errMsg);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">~</span><span style="color: #000000;">MyException()&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(errorMessage)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete[]&nbsp;errorMessage;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;errorMessage</span><span style="color: #000000;">=</span><span style="color: #000000;">NULL;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;what()&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;errorMessage;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>};<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;MyException(</span><span style="color: #000000;">"</span><span style="color: #000000;">Error&nbsp;Occured!!</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;std::exception&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">e)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">e.what()</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>}<br></span></div>
<br>
<br><br>
<br><br>
<br>   <img src ="http://www.cppblog.com/qzb2006e/aggbug/26943.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-26 22:18 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/26/26943.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The C++ Standard Library : A Tutoral and Reference 读书笔记之命名空间(2)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/25/26935.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Mon, 25 Jun 2007 13:18:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/25/26935.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26935.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/25/26935.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26935.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26935.html</trackback:ping><description><![CDATA[<span style="font-weight: bold; font-size: 14pt;">命名空间</span>是为了应对命名冲突这种情况的出现而产生的 .命名空间是可扩展的.你可以使用相同的命名空间来定义你的那些在物理上处于不同位置的组件.一个典型的例子就是namespace std.<br>你可以有三种选择来使用std命名空间.<br>1.使用std::作为前缀.<br>如:<br>std::cout &lt;&lt; std::hex &lt;&lt; 3.4 &lt;&lt; std::endl;
<br>2.使用using 进行预定义<br>using std::cout;<br>using std::endl;<br>然后这样使用:<br>cout &lt;&lt; std::hex &lt;&lt; 3.4 &lt;&lt; endl;
<br>3.直接使用using.<br>using namespace std;
<br>cout &lt;&lt; hex &lt;&lt; 3.4 &lt;&lt; endl;
<br>不要在代码上下文不明确的地方使用这种用法( 如头文件中).<br>c++标准中对于<span style="font-weight: bold; font-size: 14pt;">头文件</span>引入使用了一种新的写法,如:<br>#include &lt;iostream&gt;<br>这实际上是引入了c++的标准模板库的iostream.h文件.<br>而对于旧的c语言的头文件,可以使用这种方式引入: <br>#include &lt;cstdlib&gt; //相当于&lt;stdlib.h&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>#include &lt;cstring&gt; //相当于&lt;string.h&gt;<br>有意思的是,如果在引入头文件的时候这样写,可以把c风格的函数加上std命名空间来使用.<br>
如:
<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">cstring</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">cstdio</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%d</span><span style="color: #000000;">"</span><span style="color: #000000;">,std::strlen(</span><span style="color: #000000;">"</span><span style="color: #000000;">hello&nbsp;world!</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br>}</span></div>
<br>当然,仍然可采用兼容于c风格的头文件引入方式:<br>#include &lt;stdlib.h&gt;
<br><br><br>
<br>
<br><br> <img src ="http://www.cppblog.com/qzb2006e/aggbug/26935.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-25 21:18 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/25/26935.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔记 第二章(3)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/24/26856.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sun, 24 Jun 2007 13:35:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/24/26856.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26856.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/24/26856.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26856.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26856.html</trackback:ping><description><![CDATA[<p><strong>难以通过重构手法完成的设计改动</strong><br>比如说在一个项目中，我们很难（<span style="BACKGROUND-COLOR: yellow">但还是有可能</span>）将&#8220;无安全需求情况下构造起来的系统&#8221;重构为&#8220;安全性良好的系统&#8221;。<br>这种情况下我的办法就是&#8220;先<span style="BACKGROUND-COLOR: yellow">想象</span>重构的情况&#8221;。考虑候选设计方案时，我会问自己：将某个设计重构为另一个设计的难度有多大？ 如果看上去很简单，我就不用担心选择是否得当，于是我就会选择最简单的设计，哪怕它不能覆盖所有潜在需求也没关系。但如果预先看不出简单的重构办法，我就会在设计上投入更多力气。<br>何时不该重构？<br>重写（而非重构）的一个清楚的讯号就是：现有代码<span style="BACKGROUND-COLOR: yellow">根本不能</span>正常工作。你可能只是试着做点测试，然后就发现代码中满是错误，根本无法稳定运作。记住，重构之前，代码必须起码能够在<span style="BACKGROUND-COLOR: yellow">大部分</span>情况下<span style="BACKGROUND-COLOR: yellow">正常</span>运作。<br>另外，如果项目自己已近<span style="BACKGROUND-COLOR: yellow">最后期限</span>，你也应该<span style="BACKGROUND-COLOR: yellow">避免重构</span>。在此时机，从重构过程中赢得的生产力只有在最后期限过后才能体现出来，而那个时候已经时不我予。<br>Wrad Cunningharn的看法：未完成的重构工作是&#8220;<span style="BACKGROUND-COLOR: yellow">债务</span>&#8221;。过于复杂的代码所造成的维护和扩展的额外开销，就是<span style="BACKGROUND-COLOR: yellow">利息</span>。你可以承受一定程度的利息，但如果利息太高你就会被压垮。把债务<span style="BACKGROUND-COLOR: yellow">管理好</span>是很重要的，你应该通过重构来偿还部分债务。<br><strong>重构与设计<br></strong>Alistair Cockburn：有了设计，我可以思考更快，<span style="BACKGROUND-COLOR: yellow">但是</span>其中充满小漏洞。<br>有一种观点认为：重构可以成为&#8220;预先设计&#8221;的替代品。这意思是你根本不必做任何设计，只管按照最初想法开始编码，让代码有效运作，然后再将它重构成型。极限编程的支持者极力提倡这种办法。<br>但这不是最有效的途径。极限编程的爱好者们也会进行预先设计。他们会使用<span style="BACKGROUND-COLOR: yellow">CRC卡</span>或类似的东西来检验各种不同的想法，然后才得到第一个可被接受的解决方案，然后才开始编码，然后才能重构。关键在于：重构<span style="BACKGROUND-COLOR: yellow">改变了</span>&#8220;预先设计&#8221;的角色。如果没有重构，就必须保证&#8220;预先设计&#8221;的正确无误，这个压力太大了。<br><br></p>
<fieldset title=什么是CRC卡? style="COLOR: #0000ff; BACKGROUND-COLOR: #ffffff">什么是CRC卡?<br>CRC(Class-Responsibility-Collaborator)卡建模是一种简单且有效的面向对象的分析技术。在一个OO(面向对象)开发项目中，包括用户、分析员和开发者在建模和设计过程中经常应用CRC卡建模，使整个开发团队普遍的理解形成一致。<br>它由三部分组成：<br>1. 类(Class)<br>2. 职责(Responsibility)<br>3. 协作(Collaborator)<br>一个类代表许多类似的对象。而对象是系统模型化中关注的事物。他们可以是一个人、地方、事情、或任何对系统有重要性的概念。类名在CRC卡的顶部。<br>职责是类需要知道或做的任何事物。这些职责是类自身所知的知识，或类在执行时所知的知识。<br>协作是指为获取消息，或协助执行活动的其他类。在特定情形下，与指定的类按一个设想共同完成一个(或许多)步骤。协作的类顺着CRC卡的右边排列。<br><img height=494 alt="" src="http://www.cppblog.com/images/cppblog_com/qzb2006e/CRC.gif" width=279 border=0><br>(上图出自<a href="http://book.csdn.net/bookfiles/116/1001163602.shtml">http://book.csdn.net/bookfiles/116/1001163602.shtml</a>)</fieldset><br><br><br>在可以重构的前提下，你只需要得到一个<span style="BACKGROUND-COLOR: yellow">足够合理</span>的解决方案就够了。<br>如果你在预先设计时在所有有可能出现变化的地方都建立起灵活性，却在最后发现这些灵活性都毫无必要，这才是最大的失败。你知道，这其中肯定有些灵活性的确派不上用场，但你却无法预测到底哪些派不上用场。<br>而有了重构，则只需要考虑：把一个简单的解决方案重构成这个灵活的解决方案有多大难度？如果答案是&#8220;<span style="BACKGROUND-COLOR: yellow">相当容易</span>&#8221;，那么你就只需实现目前的<span style="BACKGROUND-COLOR: yellow">简单方案</span>就可以了。<br>重构与性能<br>虽然重构必然会使软件运行更慢，但它也使软件的性能优化更易进行。除了对性能有严格要求的实时系统，其他任
<p>&nbsp;</p>
<p>何情况下&#8220;编写快速软件&#8221;的秘密就是：首先写出<span style="BACKGROUND-COLOR: yellow">可调</span>软件，然后<span style="BACKGROUND-COLOR: yellow">调整</span>它以求获得足够速度。<br>编写快速软件的方法：<br>1、时间预算法。<br>为每个组件分配资源（包括时间资源和执行轨迹）；每个组件绝对不能超过自己的预算，就算拥有&#8220;可在不同组件之间调度预配时间&#8221;的机制也不行。例如心律调节器，在这样的系统中，迟来的数据就是错误的数据。<br>2、持续关切法。<br>要求程序员在任何时间做任何事时，都要设法保持系统的高性能。<br>这种方式通常不会起太大作用。任何修改如果为了提高性能，通常会使程序难以维护，因而减缓开发速度。性能一旦被分散到程序各个角落，每次改善都只不过是从&#8220;对程序行为的一个<span style="BACKGROUND-COLOR: yellow">狭隘</span>视角&#8221;出发而已。<br>3、利用90%统计数据<br>90%的优化都是白费劲，因为难得被执行。<br>所以以一种&#8220;良好的<span style="BACKGROUND-COLOR: yellow">分解</span>方式&#8221;来建造自己的程序，不对性能投以任何关切，直至进入性能优化阶段。<br>优化的过程：测量--&gt;优化--&gt;编译--&gt;测试--&gt;再次测量.<br>使用性能热点测量工具&#8220;发现热点、去除热点&#8221;，直到获得客户满意的性能。<br>McConnell提供了关于这项技术的更多信息。</p>
<fieldset style="COLOR: #0000ff">
<p>&nbsp;很想了解相关技术,但是没有找到具体资料.倒是有两个开源项目</p>
p-unit和<strong><font color=#6699cc>junitperf<br><a href="http://www.javapronews.com/javapronews-47-20030721ContinuousPerformanceTestingwithJUnitPerf.html">http://www.javapronews.com/javapronews-47-20030721ContinuousPerformanceTestingwithJUnitPerf.html</a></font></strong></fieldset> 
<img src ="http://www.cppblog.com/qzb2006e/aggbug/26856.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-24 21:35 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/24/26856.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The C++ Standard Library : A Tutoral and Reference 读书笔记之 第二章扫尾</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/20/26729.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Wed, 20 Jun 2007 14:50:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/20/26729.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26729.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/20/26729.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26729.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26729.html</trackback:ping><description><![CDATA[<span style="font-weight: bold;">静态常量的初始化</span><br>书中说:现在可以在类结构中初始化整型的静态成员了(难道以前不可以?).我想书中大概是这个意思:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;MyClass<br>{<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;num</span><span style="color: #000000;">=</span><span style="color: #000000;">100</span><span style="color: #000000;">;<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;values[num];<br>};<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>std::cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">MyClass::num;<br>}</span></div>
<span style="font-weight: bold;">main的声明</span><br>在c++标准中只有两种main函数的写法会被接受:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"><br>}<br></span></div>
<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"><br>}<br></span></div>
与C语言不同,C++在main中没有返回值的情况下,会隐式的返回0.但这种情况,编译器在编译的时候,会给你警告.<br><span style="font-weight: bold;">复杂度问题和大写的O标志<br></span>大写的O标志是用来考量一个算法的时间复杂度的.如果运算的时间与运算元素的个数接近于正比,那么时间复杂度就是O(n).当然除此之外,还有幂级的时间复杂度.这里强调的是,c++ 中的数学库中一些算法的实现都仔细考虑了时间复杂度的问题.<br><br><span style="font-weight: bold;"></span><img src ="http://www.cppblog.com/qzb2006e/aggbug/26729.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-20 22:50 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/20/26729.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔记 第一章(2)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/20/26656.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Wed, 20 Jun 2007 13:42:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/20/26656.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26656.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/20/26656.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26656.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26656.html</trackback:ping><description><![CDATA[<p align=left><strong>运用多态(polymorphism)取代与价格相关的条件逻辑</strong><br>在另一个对象的属性基础上运行switch语句，并不是什么好主意。如果不得不使用，也应该在对象自己的数据上而不是在别人的数据上使用。选择对象之间的传递关系的时候，应当考虑选择将稳定的对象的属性传递给易变的对象（如书中的将租期长度来自Rental（稳定，不易变）传递给Movie（不稳定，易变））。<br>对于类A和类B，如果A中存在因B而变化的属性或方法体，则将它们移动到B中，A中只保留移动后B暴露给A的接口（或方法）。<br><strong>终于.......我们来到继承(inheritance)</strong><br>此部分包含的重构方法：<br>Self Encapsulate Field：自封装域。<br>Move Method：移动方法。<br>Replace Conditional with Polymorphism：用多态替换条件选择。<br>Replace Type Code with State/Strategy：在这个方法中使用了上面三个方法作为步骤。即用状态、策略替换代码，将与类型相依的行为搬移到模式内。在使用它的时候，多使用对于以类型相依的行为进行Self Encapsulate Field作为第一步骤。从而确保任何时候都通过getter和setter两个函数来运行这些行为。第二步通常采用Move Method方法，即把代码从超类的宿主中搬移到子类中去。第三步采用Replace Conditional with Polymorphism方法，将switch，if等条件分支语句转变为多态形式。<br>下面是一个小实验：<br>一、重构之前的代码：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ClassA&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue(TheType&nbsp;type)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">(type)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;SmallValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;MidValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;BigValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">300</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String&nbsp;args[])<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ClassA&nbsp;instanceA</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ClassA();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">theValueIs:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">instanceA.getValue(TheType.SmallValue));<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<p align=left>应用Self Encapsulate Field之后的效果：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ClassAModified&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/**</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000">&nbsp;args<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;TheValue&nbsp;_theValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue(TheType&nbsp;type)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">(type)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;SmallValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;MidValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;BigValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">300</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;TheValue&nbsp;get_theValue()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_theValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;set_theValue(TheType&nbsp;type)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>}<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TheValue<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div>
<p align=left>应用Move Method之后的效果：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ClassAModified&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;args<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;TheValue&nbsp;_theValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue(TheType&nbsp;type)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_theValue.getValue(type);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;TheValue&nbsp;get_theValue()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_theValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;set_theValue(TheType&nbsp;type)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_theValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;TheValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TheValue<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue(TheType&nbsp;type)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">(type)<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;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;SmallValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;MidValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;BigValue:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">300</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<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;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br><br>}</span></div>
<p align=left>&nbsp;应用Replace Conditional with Polymorphism之后的效果：<br></p>
<p align=left></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ClassAModified&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;args<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;TheValue&nbsp;_theValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue(TheType&nbsp;type)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_theValue.getValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;TheValue&nbsp;get_theValue()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;_theValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;set_theValue(TheType&nbsp;type)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">(type)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;SmallValue:_theValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;SmallValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;MidValue:_theValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;MidValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;BigValue:_theValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;BigValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:_theValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;TheValue();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TheValue<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;SmallValue&nbsp;extends&nbsp;TheValue<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MidValue&nbsp;extends&nbsp;TheValue<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;BigValue&nbsp;extends&nbsp;TheValue<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;getValue()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">300</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>}</span></div>
<p align=left><strong>结语</strong><br>重构的节奏：测试、小修改、测试、小修改、测试、小修改。。。<br>正是这种节奏让重构得以快速而安全的前进。<br>&nbsp;</p>
<p align=left><br>&nbsp;</p>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/26656.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-20 21:42 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/20/26656.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据结构读书笔记（用栈替代递归）</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/17/26499.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sun, 17 Jun 2007 09:19:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/17/26499.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26499.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/17/26499.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26499.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26499.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据结构上面在讲到栈的时候，顺便提了一下递归。实际上递归就是用栈来实现的。在很多算法书上，对于一些用递归方式写成的算法，相应的也给出了栈的算法。这里我要把fibonacci数列分别用递归和栈的方式写出来，由于我以前的算法教材丢失了，而数据结构中也没有给出相应的伪码，所以只有自己从头写起了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先是fibonacci的递归写法（不是很标准，但是很亲切）：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fib(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;value)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">value)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">value)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;fib(value</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">fib(value</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接下来要把这个算法转换为使用栈的写法。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先进行一下分析。递归是逆向求结果的，对于不能求出结果的函数，先将运行场景压栈，然后递归调用自己，如果仍然不能出结果，就再将运行场景压栈，一直到函数可以返回结果为止。此时依次将运行场景弹栈，完成运行场景，取得返回值，再弹栈......印象中的递归调用过程就是如此。如果我们要自己写递归求fibonacci数列，就要自己手动用程序来模拟这个过程。我首先准备一个栈来存放结果序列。在这个结果序列里面，保证第一个结果和第二个结果总是可以直接求得的数值。因为只需要n-1和n-2便能求出fib(n)，所以我们在算法中要把多余的n-3弹出，这样栈内的元素个数在每一次调用的过程中逐渐减少，一直到里面只剩下一个元素，在这个时候，刚才弹出的两个元素之和就是我们要求的fibonacci(n)。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是算法：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fibByStack(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;value)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;currentValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;currentValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">value;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(currentValue</span><span style="COLOR: #000000">&gt;=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fibStack.push(currentValue);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currentValue</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;fibStack.pop();<br>&nbsp;&nbsp;&nbsp;&nbsp;fibStack.pop();<br>&nbsp;&nbsp;&nbsp; //1和0是n=1和n=0时的值，为了强调压入的是&#8220;结果&#8221;，我将头两个元素弹出再压入这两个值<br>&nbsp;&nbsp;&nbsp;&nbsp;fibStack.push(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;fibStack.push(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;topValue1,topValue2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;topValue1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fibStack.top();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fibStack.pop();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;topValue2</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fibStack.top();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fibStack.pop();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">fibStack.size())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;topValue1</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">topValue2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fibStack.pop();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fibStack.push(topValue1</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">topValue2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fibStack.push(topValue2);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/26499.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-17 17:19 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/17/26499.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The C++ Standard Library : A Tutoral and Reference 读书笔记之 类型转换(1)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/17/26347.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sun, 17 Jun 2007 06:56:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/17/26347.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26347.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/17/26347.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26347.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26347.html</trackback:ping><description><![CDATA[在阅读类型转换之前,还是先看一下关键字explicit(显式)<br>书上的例子中的类名叫做Stack,这样总感觉有些误解,因为栈这个概念已经在我们的脑海中先入为主了,容易形成思维定式.那么我写一个和其他任何概念都无关的例子:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyClass<br>{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_number;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;MyClass(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;number)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_number</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">number;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};</span></div>
上面的类很普通,没什么特别的.我们可以这样创建这个类的对象:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;MyClass&nbsp;instance</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">;<br>}</span></div>
这就比较有意思了,c++还能这样写,我以前的确没有见过.那么explicit关键字的作用就是不让你这样写,如果你这样写了,编译器就会给你一个错误提示.现在改造一下MyClass<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyClass<br>{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_number;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">explicit</span><span style="COLOR: #000000">&nbsp;MyClass(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;number)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_number</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">number;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};</span></div>
main函数不变的情况下,编译器会这样提示你:<br>Explicit.cpp: In function &#8216;int main()&#8217;:<br>Explicit.cpp:14: 错误： conversion from &#8216;int&#8217; to non-scalar type &#8216;MyClass&#8217; requested<br>这样,就只能这样写了:<br>MyClass instance(5); <br>好了,下面开始阅读类型转换的部分.<br>1 static_cast<br>这个操作符的执行过程可以被认为是:它创建了一个新的对象,然后用要转换的值去初始化这个新对象.这个转换只有当一个类型转换被声明过才能执行.<br>首先是一个简单的例子:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #008000">//</span><span style="COLOR: #008000">一个简单的类型转换</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;valueToBeConverted</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">();<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br>&nbsp;&nbsp; cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">static_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(valueToBeConverted)</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;</span></div>
很像其他语言中的显式类型转换.那么对于我自己的类如何进行转换呢?可以看一下下面的这个例子:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyClass2<br>{<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;IntMember1;<br>&nbsp;&nbsp;&nbsp;MyClass2()<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntMember1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;}<br>};<br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyClass1<br>{<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;IntMember1;<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;f()<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">IntMember1</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;</span><span style="FONT-WEIGHT: bold; COLOR: #0000ff">explicit</span><span style="COLOR: #000000">&nbsp;MyClass1(MyClass2&nbsp;instance)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IntMember1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">instance.IntMember1;<br>&nbsp;&nbsp;&nbsp;}<br>};<br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;MyClass2&nbsp;mc2Instance;<br>&nbsp;&nbsp;&nbsp;MyClass1&nbsp;mc1Instance</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">static_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">MyClass1</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(mc2Instance);<br>&nbsp;&nbsp;&nbsp;mc1Instance.f();<br>}<br></span></div>
注意看上面的粗体字explicit.如果没有explict对于构造函数的修饰,那么万全可以简单爽快的这么写: <br>MyClass1&nbsp;mc1Instance=mc2Instance; <br>换句话说,如果你想让别人写代码的时候不关心类型,舒舒服服的写出你认为不安全的代码,那么你就去掉explicit,如果你想让别人在写代码的时候,让那些不安全的类型转换变得更加"显眼"一些,那么你就按上面这样写.然后让编译器狠狠的给他们一个警告.<br>2 dynamic_cast<br>This operator enables you to downcast a polymorphic type to its real static type. This is<br>the only cast that is checked at runtime. Thus, you could also use it to check the type of a<br>polymorphic value. <br><br>这个运算符能够让你把一个多态的类型转换成它的真实的静态类型.这是唯一的在运行时进行检验的转换方法.所以你同样需要在转换之前检验多态值的类型.<br>首先dynamic_cast只能够用于指针或者引用.否则编译器会告诉你类似这样的错误:<br>&nbsp;无法将 &#8216;scInstance&#8217; 从类型 &#8216;SubClass&#8217; 动态转换到类型 &#8216;class BaseClass&#8217; (target is not pointer or reference)<br>这里使用书中的例子:<br>&nbsp;
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Car;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;至少拥有一个抽象函数的抽象类</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Cabriolet&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Car&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"><br>&nbsp;&nbsp;&nbsp;};<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Limousine&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Car&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"><br>&nbsp;&nbsp;&nbsp;};<br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f(Car</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;cp)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cabriolet</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dynamic_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Cabriolet</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(cp);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(p&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">p并非Cabriollet类型</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}</span></div>
<br>In this example, f() contains a special behavior for objects that have the real static type<br>Cabriolet. When the argument is a reference and the type conversion fails,<br>dynamic_cast throws a bad_cast exception (bad_cast is described on page 26).<br>Note that from a design point of view, it it always better to avoid such type-dependent<br>statements when you program with polymorphic types.<br>当参数是一个引用并且类型转换失败的时候,dynamic_cast会抛出一个bad_cast异常.值得注意的是,从设计的角度来说,通常在进行多态类型的程序编写时,应该避免这样的类型依赖.<br>3 const_cast<br>This operator adds or removes the constness of a type. In addition, you can remove a<br>volatile qualification. Any other change of the type is not allowed.<br>这个操作符添加或除去一个类型的常量化(特性).另外,你可以除去一个变量变化的能力.任何对于这个类型变量的变化都将不被允许.<br>让常量可修改的例子:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyClass<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;MemberValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;showValue()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">My&nbsp;Value&nbsp;is</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">MemberValue</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyClass()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MemberValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br>};<br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;MyClass&nbsp;myValue;<br>&nbsp;&nbsp;&nbsp;&nbsp;MyClass&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">ptr</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">const_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">MyClass</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">myValue);<br>&nbsp;&nbsp;&nbsp;&nbsp;ptr</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">MemberValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;ptr</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">showValue();<br>}</span></div>
上面的例子只是将一个const变得可以修改了,但是注意到书中的这样一句:<br>In addition, you can remove a<br>volatile qualification. Any other change of the type is not allowed. <br>似乎还可以将一个可变量转换为非可变的,这里没有查到相关资料,也许书的后面会有相应解释,所以这里先放一放.<br>4 reinterpret_cast <br>这个比较有趣,支持不兼容类型之间的转换.以下是例子:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ClassA<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Value1;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Value2;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Value3;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;showValue()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">Value1</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">Value2</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">Value3</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};<br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ClassB<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Value1;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Value2;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Value3;<br>&nbsp;&nbsp;&nbsp;&nbsp;ClassB()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value2</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value3</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};<br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;ClassB&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ClassB();<br>&nbsp;&nbsp;&nbsp;&nbsp;ClassA&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">reinterpret_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ClassA</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(b);<br>&nbsp;&nbsp;&nbsp;&nbsp;a</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">showValue();<br>}</span></div>
同样,这种转换对于非基本类型来说,仍然只能支持指针和引用.<br>这些运算符的优点就是他们明确了类型转换的意图,并且能够让编译器获取更多的信息来了解这些类型转换的原因,然后当这些转换操作越过他们的职能的时候,编译器会报告错误.<br>另外需要注意的是,这些类型转换都只能接受一个参数.看下面的例子:<br>&nbsp;&nbsp;&nbsp; static_cast&lt;Fraction&gt;(15,100)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>上面不会产生你想要的结果.这里的逗号并不是用来连接两个参数的,而是作为逗号运算符出现,这里15会被舍弃,而采用100作为参数构造Fraction.<br>所以还是需要采用下面的方法才合适:<br>&nbsp;&nbsp;&nbsp; Fraction(15,100)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br><br><br><br><br>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/26347.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-17 14:56 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/17/26347.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构--改善既有代码的设计读书笔记 第一章(1)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/15/26400.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Fri, 15 Jun 2007 14:53:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/15/26400.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26400.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/15/26400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26400.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26400.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以前看过一点这本书的英文版本,感觉相当不错,但是由于英文水平有限,总是感觉里面有些说法对我来说比较生涩,特别还有一些理论性的东西,如果只看英文,基本上是无从查起的.好在这本书有了中文版(也许早就有了,我可是才刚刚找到),高兴之余,细细品读,写写笔记,潦记于此.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先看看书中有关重构的定义：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重构的定义：在<span style="BACKGROUND-COLOR: yellow">不改变</span>代码<span style="BACKGROUND-COLOR: yellow">外在行为</span>的前提下，对代码做出修改，以<span style="BACKGROUND-COLOR: yellow">改进</span>程序的<span style="BACKGROUND-COLOR: yellow">内部结构</span>。本质上说，重构就是在代码写好之后改进它的设计。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个定义说得很清楚了，基本上不需要进行任何的说明。我们只要将它当作原则去遵照就好了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后书中讲了：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 快速而随性(quick and dirty)的设计一个简单的程序并没有错。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 于是我就有这样的问题了：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 什么规模的程序才值得重构？<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后书中给了我这样一个回答：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你发现自己需要为程序添加一个特性，而代码结构使你<span style="BACKGROUND-COLOR: yellow">无法很方便</span>的那么做，那就先重构那个程序，使特性的添加比较容易进行，然后添加特性。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;重构之前要做这样一些准备：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;重构的第一步--为代码建立测试环境。<br>重构之前，首先检查自己是否有一套可靠的测试机制。这些测试必须有自我检查能力。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是一些摘录：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先在代码中找出函数内的局部变量和参数。任何不会修改的变量都可以被当成参数传入新的函数，至于会被修改的变量就需要格外小心。如果只有一个变量会被修改，可以把它当作返回值。<br>在找出一个函数的逻辑泥潭并将之提练到另外一个函数中的时候，要格外注意返回值。如果你经常犯这样的错误，那么一定确保在修改前后函数的调用结果相一致。 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 代码应该表现自己的目的，这一点非常重要。<span style="BACKGROUND-COLOR: yellow">阅读代码的时候，我经常进行重构</span>。这样，随着对程序的理解逐渐加深，我也就不断地把这些理解嵌入代码中，这么一来才不会遗忘我曾经理解的东西。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 几个重构的方法（下面的伪码是我自己写的）：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、Extract Method （提取方法）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、appending assignment ,operator+=（ 附添赋值动作）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这两种重构方法结合的形式为：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重构前：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(expression)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重构后：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A+=function1();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TypeOfA function1()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(expression)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、Replace Temp with Query（字面上用查询取代临时变量）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 利用所谓的query method来取代临时变量。由于class内的任何函数都可以取用（调用）所谓query methods,所以它能够促进比较干净的设计，而非冗长复杂的函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Replace Temp with Query的伪码例子：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(expression)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "The Result is "+A;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面A是一个临时变量.所以可以用一个querymethod来取代：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TypeA function1()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(expression)<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;&nbsp;&nbsp; A++;<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; return A;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>这样主程序可以这样写:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "The Result is "+function1();<br>继续摘抄：<br>重构可能会存在另外一个问题，就是性能。原本代码只执行一次循环，在重构以后可能要执行三次。如果循环中的语句耗时很多，就可能大大降低程序的性能。单单为了这个原因，许多程序员就不愿进行这个重构动作。但是请注意这里只是&#8220;可能&#8221;。除非进行评测，否则无法确定循环的执行时间，也无法知道这个循环是否经常使用以至于影响系统的整体性能。重构时程序人员不必担心这些，优化时才去担心它们，但那时候你已经处于一个比较有利的位置，有更多选择可以进行有效优化。<br>使用Form Template Method（字面上建立模板方法）可以进一步减少重复代码。这会在书后面的章节讲到。 
<img src ="http://www.cppblog.com/qzb2006e/aggbug/26400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-15 22:53 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/15/26400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The C++ Standard Library : A Tutoral and Reference 读书笔记之命名空间</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/14/26279.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Thu, 14 Jun 2007 14:06:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/14/26279.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26279.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/14/26279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26279.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26279.html</trackback:ping><description><![CDATA[在这一部分之前,书中介绍了基本类型的显式初始化以及简单的异常处理.<br>基本类型的显式初始化是比较简单的.就是说你在定义一个整型变量的时候,有两种不同的情况:<br>int i1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // undefined value<br>int i2 = int(); // initialized with zero<br><br>
如果按照前一种,会作"值未定义;如果按照后一种,则自动被初始化为0.这样也就确保了你的类在初始化的时候有一个确定的初始值.<br>至于异常的处理等问题,书中会在后面有比较详细的描述.这里可以看到比较有意思的一点,就是指定函数抛出的异常类型,这于Java很像:<br>void f() throw(bad_alloc);
<br>下面转入正题:命名空间.<br>有了命名空间,它将会取代函数和类作用于全局,并作为它所统领的那些类和函数的唯一标识存在.这样可以避免命名冲突情况的出现.正如书中所说:<br>Unlike classes, namespaces are open for definitions and extensions in different modules. Thus<br>you can use namespaces to define modules, libraries, or components even by using multiple<br>files. A namespace defines logical modules instead of physical modules (in UML and other<br>modeling notations, a module is also called a package).<br><br>
可以像这样定义一个命名空间: <br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;MyNameSpace<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;MyClass<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;_classInfo;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;getClassInfo()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;_classInfo;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyClass(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;info)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_classInfo</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">[strlen(info)];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(_classInfo,info);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">~</span><span style="color: #000000;">MyClass()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(_classInfo)<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;&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">free&nbsp;classinfo</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete[]&nbsp;_classInfo;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;};<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;printMyClassInfo(MyClass&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">instance)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">instance.getClassInfo();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
从上面可以看出,这个命名空间里面包括了一个类和一个函数.类中包含了char*类型的成员变量.函数printMyClassInfo 以一个MyClass类型的引用作为参数.为什么要用引用呢?熟悉c++的人应当很清楚,我是通过实验才刚刚知道原因.这个原因我将会在后面说明.<br>好现在来看一下调用过程,通常的调用过程是这样的:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;MyNameSpace::MyClass&nbsp;instance(</span><span style="color: #000000;">"</span><span style="color: #000000;">MyClass!\n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;MyNameSpace::printMyClassInfo(instance);<br>}</span></div>
这没有任何问题,但有意思的是,还可以这样调用:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;MyNameSpace::MyClass&nbsp;instance(</span><span style="color: #000000;">"</span><span style="color: #000000;">MyClass!\n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;printMyClassInfo(instance);<br>}</span></div>
看来c++中在使用一个命名空间的类或者函数的时候,这个命名空间就被"自动"引入了.当寻找函数printMyClassInfo的时候会在当前的上下文中进行寻找的同时,还会到以前用到过的命名空间中去寻找.<br>当然,通常情况下我们喜欢这样做:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;MyNameSpace;&nbsp;<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;MyClass&nbsp;instance(</span><span style="color: #000000;">"</span><span style="color: #000000;">MyClass!\n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;printMyClassInfo(instance);<br><br>}</span></div>
但是并不是在任何情况下都鼓励using namespace这种做法的.在书中将得比较清楚:<br>Note that you should never use a using directive when the context is not clear (such as in header<br>files, modules, or libraries). The directive might change the scope of identifiers of a namespace,<br>so you might get different behavior than the one expected because you included or used your<br>code in another module. In fact, using directives in header files is really bad design.<br><br>
上面这段话强调了当上下文并不明确的情况下(比如在一个头文件,组件或者库里面),不要使用using这种写法,这个指令会改变命名空间标识符的作用域,这样你就有可能引发和你预期不相同的行为,因为你会在另外一个组件中引用你的代码或使用它.事实上,将using标识符写在头文件里面是一种相当不好的设计.<br>在这里,我看了一下c++程序设计语言这本书,发现命名空间除了像上面这样声明以外,还可以像类一样这样来写:<br>在命名空间中这样定义<br>void printMyClassInfo(MyClass &amp;);
<br>然后在外面写函数的主体<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;MyNameSpace::printMyClassInfo(MyClass&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">instance)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">instance.getClassInfo();<br>}</span></div>
好了,写了这么多,再来看看刚才留下来的那个问题.<br>其实很简单,一个函数如果传递的是值,那么就会在内存中产生一个一模一样的"复本",而那个字符指针也会被复制一次.当传送的值超过它的作用域的时候 ,就会被释放掉,而被复制的"本体"在程序运行结束之后,又会被"释放一次".这样在运行的时候,它会提示你这样的错误: <br>*** glibc detected *** double free or corruption (fasttop): 0x0804a008 ***<br><br>
在我们的MyClassl类的析构中,我们有一个输出,所以这里就输出了两次:<br>free classinfofree classinfo<br><br>
<br><br><br>    <img src ="http://www.cppblog.com/qzb2006e/aggbug/26279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-14 22:06 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/14/26279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>富爸爸投资指南读书笔记</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/13/26267.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Wed, 13 Jun 2007 11:42:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/13/26267.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26267.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/13/26267.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26267.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26267.html</trackback:ping><description><![CDATA[<p>富爸爸研究过公司法和税法，并找到了利用法律为他赚很多钱的方法。<br>mortgage<br>KK: []<br>DJ: []<br>抵押贷款，源于法语mortir，法语意思是死亡，因而抵押贷款就是直到死的一种契约<br>real estate<br>KK: []<br>DJ: []<br>不动产，并不是&#8220;真正&#8221;的财产，来自于西班牙语，意思是贵族的财产。<br>我们仅仅是在技术上控制了不动产，却并不能占有它，政府占有这些财产，向我们征收不动产税。<br>奥肖内西 华尔街股市投资经典<br>What Works On Wall Street:A Guide to the Best Performing In-vestment Strategies of All Time<br>提出两种不同的决策方法：<br>经验型的分析方法或称直觉式分析方法。该方法以知识，经验和常识为基础。<br>定量分析法或称精确统计法。这种方法以大量数据为基础，推论出各种关系。<br>在多数情况下，直觉分析法的投资者常常做出错误的决定，或败给几乎纯机械的方法。即：人类的推断力远小于我们所想象的。</p>
<p>企业取得权 不动产组合 购买抵押品 贴现合同 投资研讨班 罗宾逊准则<br>有些东西你的眼睛是看不到的，不动产就是不动产，股票就是公司股票，这些东西你能看到，但是你看不出什么事重要的。决定某种东西是不是一项好的投资的还有：交易、财务协议、市场、管理、风险因素、现金流、企业结构、税法和很多其他的事情。<br>你为什么要付这么高的利率？你认为你的投资回报是多少？这项投资于你的长期财务战略吻合吗？你打算用多大比例计算修理费用？你知道这个城市刚刚宣布要在那个地区修路以改善交通状况吗？一条大道就要从你的房前穿过，你知道这些吗？我知道现在市场看好，但是你知道是什么在驱动市场，商业经济还是贪婪？你认为这种趋势会维持多久？如果你的房子租不出去，你将怎么办？</p>
<p>建议并不是现实.<br>成为--&gt;做--&gt;拥有<br>大多数人追求做而不是追求&#8220;成为&#8221;<br>一个拥有失败者心态的人将一直失败<br>不要在对方身上下功夫，而要在你对对方的看法上下功夫<br>丹尼尔 格鲁曼 《情商》<br>父母会说很多的&#8220;应该&#8221;，小孩说很多的&#8220;感觉&#8221;<br>父母并不一定就是成年人<br>作为一个成年人应当意识到你必须去做什么并且去做，即使你可能感觉上并不喜欢做这件事<br>我的富爸爸不许我说：<br>&#8220;我付不起钱&#8221;<br>&#8220;我做不到&#8221;<br>&#8220;做事要稳妥&#8221;<br>&#8220;别赔钱&#8221;<br>&#8220;如果你失败了并且再也翻不了身，该怎么办？ &#8221;<br>他不许我说这些是因为他坚信语言是人类最有影响力的工具，一个人所说的和所想的终将变为现实。<br>用圣经里面的话即使：<br>语言将变为血肉，留在我们体内。</p>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/26267.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-13 19:42 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/13/26267.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据结构读书笔记（栈：不只是C++的东西）</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/11/26104.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Mon, 11 Jun 2007 14:11:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/11/26104.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26104.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/11/26104.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26104.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26104.html</trackback:ping><description><![CDATA[栈在概念方面确实没有提的必要了。看了数据结构的这一部分，就将书中的一小段代码实现了。这里用到了标准库中的stack。下面就是根据输入的十进制正数获取二进制正数的程序（书上是八进制）：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stack</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;stack</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;binaryStack;<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;decimalValue;<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">please&nbsp;input&nbsp;decimal&nbsp;value:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;cin</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">decimalValue;<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(decimalValue)<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;binaryStack.push(decimalValue</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;decimalValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">decimalValue</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">the&nbsp;binary&nbsp;result&nbsp;is:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">binaryStack.empty())<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;result</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">)binaryStack.top();<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;binaryStack.pop();<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">result;<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">}</span></div>
另外顺便看了一下C#和JAVA，当然也支持栈。但是这些东西在我平时使用的时候却很少用到，或者在用到的时候去&#8220;重复发明轮子了&#8221;。作为一个经典的数据类型，栈理应是被绝大多数语言支持的（不知道PB怎样）。所以在这里要树立一下&#8220;重用轮子&#8221;的意识：<br>C#的十进制转二进制实现：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Class1<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;summary&gt;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;应用程序的主入口点。<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;/summary&gt;</span><span style="COLOR: #808080"><br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #808080"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[STAThread]<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Main(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">[]&nbsp;args)<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;TODO:&nbsp;在此处添加代码以启动应用程序<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stack&nbsp;binaryStack</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Stack();<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Please&nbsp;input&nbsp;decimal&nbsp;value:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sDecimal</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">Console.ReadLine();<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;decimalValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">Int32.Parse(sDecimal);<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(decimalValue</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;binaryStack.Push(decimalValue</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;decimalValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">decimalValue</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">The&nbsp;binary&nbsp;result&nbsp;is:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(binaryStack.Count</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.Write(binaryStack.Pop());<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">26</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine();<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br>JAVA的十进制转二进制实现：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.io.BufferedReader;<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.io.InputStreamReader;<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.util.Stack;<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;hello1&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String&nbsp;args[])<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stack</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Integer</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;binaryStack</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Stack</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Integer</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;decimalValue;<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">please&nbsp;input&nbsp;decimal&nbsp;value:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedReader&nbsp;bufferedReader</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;BufferedReader(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;InputStreamReader(System.in));<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;decimalValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">Integer.parseInt(bufferedReader.readLine());<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(decimalValue</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;binaryStack.push(decimalValue</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;decimalValue</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">decimalValue</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">the&nbsp;binary&nbsp;result&nbsp;is:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">binaryStack.empty())<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(binaryStack.pop());<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(Exception&nbsp;e)&nbsp;{<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">26</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">29</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">30</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">31</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
通过比较，会发现C#不大有&#8220;栈&#8221;的感觉，JAVA和C++更贴近于《数据结构》中对于数据类型&#8220;栈&#8221;的操作的定义。另外支持模板或者范型的特点让人用起来总会感觉十分舒服。在这里提醒自己：以后这三种语言有&#8220;栈&#8221;可用了！
<img src ="http://www.cppblog.com/qzb2006e/aggbug/26104.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-11 22:11 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/11/26104.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据结构读书笔记（冒泡排序:不要只注意最坏的情况） </title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/10/26004.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sun, 10 Jun 2007 14:34:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/10/26004.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/26004.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/10/26004.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/26004.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/26004.html</trackback:ping><description><![CDATA[<p>数据结构第一章讨论了一些有关算法的问题.在这一部分再次引入了那个经典的算法--冒泡排序法。<br>如果让我来描述一下这个算法的过程的话，我会这样描述：<br>从第一个元素开始和依次进行比较，大的那个放在后面，一直到最后一个元素。这样最后一个元素就会成为最大的那个；除刚才产生的最大的那个元素外，再次从头开始比较，一直到第一个元素没得可比为止。<br>这是我的理解。进而通过这个理解，我可以写出这个算法来。这没有问题。但是当我看到原版的算法的时候，我立即就感觉出差别来了：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;bubble_sort(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a[],</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n)<br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">3</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">n</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,change</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">TRUE;i</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">change;</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">i)<br></span><span style="COLOR: #008080">4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">5</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;change</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">FALSE;<br></span><span style="COLOR: #008080">6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(j</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;j</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">i;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">j)<br></span><span style="COLOR: #008080">7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(a[j]</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">a[j</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]{a[j]</span><span style="COLOR: #000000">&lt;--&gt;</span><span style="COLOR: #000000">a[j</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">];change</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">TRUE;}<br></span><span style="COLOR: #008080">8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">9</span>&nbsp;<span style="COLOR: #000000">}</span></div>
注意变量change。这里体现的思路是：如果在某一次比较过程中没有移动任何元素，那么就没有必要再从头比较一次了。因为实际上已经得到了一个排好序的数组。<br>这样对于相当多的情况来讲，减少了很多的不必要操作，自然平均时间复杂程度就降低了。<br>因为我往往只考虑到比较坏甚至极端的情况（比如完全逆序），所以自然就会忽略这些看上去不太坏，甚至是非常好的情况，这样一个直接的结果就是让那些好的情况下的操作也变得繁琐异常，而仅仅是为了照顾那些比较难于出现的个别异常情况，现在想想，这样做不可取。日后应当注意。
<img src ="http://www.cppblog.com/qzb2006e/aggbug/26004.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-10 22:34 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/10/26004.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The C++ Standard Library : A Tutoral and Reference 读书笔记之 模板(1)</title><link>http://www.cppblog.com/qzb2006e/archive/2007/06/09/25936.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Sat, 09 Jun 2007 15:53:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2007/06/09/25936.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/25936.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2007/06/09/25936.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/25936.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/25936.html</trackback:ping><description><![CDATA[最近开始系统学习STL.首先找到这本书--The C++ Standard Library : A Tutoral and Reference然后一边看书一边找着里面的例子做做.个人认为比较重要的内容将会在这里进行记录.<br>与此相关的阅读和实验过程都是在linux下进行的,所以这些读书笔记也会在linux下完成.这里不由得感叹一下--博客园的博客系统的通用性确实做得非常好,至少我在fire fox下面下使用没有感觉到任何的差别.<br>首先是模板Template.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">template</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;<br></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;MyClass<br>{<br></span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br>T&nbsp;value;<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;T&nbsp;getValue()<br>{<br></span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;value;<br>}<br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;assign(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">m)<br>{<br>value</span><span style="color: #000000;">=</span><span style="color: #000000;">m.value;<br>}<br><br>MyClass(T&nbsp;theValue)<br>{<br>value</span><span style="color: #000000;">=</span><span style="color: #000000;">theValue;<br>}<br><br>};</span></div>
<br>上面的MyClass就是我的模板类.然后我按照如下的方式进行调用,是没有问题的:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;i1(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br>MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;i2(</span><span style="color: #000000;">2</span><span style="color: #000000;">);<br>cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">\n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">i1.getValue()</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">\n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">i2.getValue()</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">\n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>i1.assign(i2);<br>cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">i1.getValue()</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">\n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);</span></div>
但是如果这样,就会出现问题.<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;i1(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br>MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">float</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;f3(</span><span style="color: #000000;">3.9</span><span style="color: #000000;">);<br>f3.assign(i1);</span></div>
编译器会告诉你:<br>TemplateExp.cpp: In function &#8216;int main()&#8217;:<br>TemplateExp.cpp:36: 错误： 对 &#8216;MyClass&lt;float&gt;::assign(MyClass&lt;int&gt;&amp;)&#8217; 的调用没有匹配的函数<br>TemplateExp.cpp:13: 附注： 备选为： void MyClass&lt;T&gt;::assign(const MyClass&lt;T&gt;&amp;) [with T = float]<br>因为在编译器看来<br><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;assign(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">int</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">m)和<br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;assign(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">float</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">m)是不同的.<br>这样就必须assign进行修改.我在这里建立了一个新的函数assignX,如下:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">template&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;X</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;assignX(MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">X</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">m)<br>{<br>value</span><span style="color: #000000;">=</span><span style="color: #000000;">m.getValue();<br>}</span></div>
在调用的时候 这样写就没有问题了:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;i1(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br>MyClass</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">float</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;f3(</span><span style="color: #000000;">3.9</span><span style="color: #000000;">);<br>f3.assignX(i1);<br>cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">f3.getValue()</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">\n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br>exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);</span></div>
有一点需要注意,在assignX中,不能够只接使用m.value而要使用m.getValue().正如书中所说:<br>Note that the argument x of assign() now differs from the type of *this. Thus, you can't<br>access private and protected members of MyClass&lt;&gt; directly. Instead, you have to use<br>something like getValue() in this example.<br>由于类型不同了(即MyClass&lt;float&gt;不同于MyClass&lt;int&gt;)所以就不能使用this.因而要另外建立一个获取值的函数.<br>实际上上面写的代码和书中还是有所不同的.比较重要的区别是函数assign.<br>书中的参数为:<br>template&lt;class X&gt;<br>assign(const MyClass&lt;X&gt;&amp; x)<br>这样实际上是不能得到x.getValue()的.编译器会给出这样的提示:<br>TemplateExp.cpp:36:&nbsp;&nbsp; instantiated from here<br>TemplateExp.cpp:20: 错误： passing &#8216;const MyClass&lt;int&gt;&#8217; as &#8216;this&#8217; argument of &#8216;const T MyClass&lt;T&gt;::getValue() [with T = int]&#8217; discards qualifiers<br>但是修改成<br></span><span style="color: #000000;">template&lt;class X&gt;<br>
assign(MyClass&lt;X&gt;&amp; x)<br>就不会有问题了<br></span><img src ="http://www.cppblog.com/qzb2006e/aggbug/25936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2007-06-09 23:53 <a href="http://www.cppblog.com/qzb2006e/archive/2007/06/09/25936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Domain-Driven Design: Tackling Complexity in the Heart of Software 语句精摘.3. </title><link>http://www.cppblog.com/qzb2006e/archive/2006/08/31/11903.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Thu, 31 Aug 2006 15:22:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2006/08/31/11903.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/11903.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2006/08/31/11903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/11903.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/11903.html</trackback:ping><description><![CDATA[
		<p>
				<span class="docEmphStrong">Chapter Three. Binding Model and Implementation<br />If the design, or some central part of it, does not map to the domain model, that model is of little value, and the correctness of the software is suspect. At the same time, complex mappings between models and design functions are difficult to understand and, in practice, impossible to maintain as the design changes. A deadly divide opens between analysis and design so that insight gained in each of those activities does not feed into the other.<br />        如果一种设计,或者它的一些核心并没有与域模型相关联，那么这个模型就没有价值，并且以此而开发出来的软件的正确性也值得怀疑。同时，模型与功能设计之间复杂的对应关系会变得难于理解，并且当设计变化的时候，它们将很难维护。一种致命的分歧就此在分析与设计之间出现，以至于那些分析设计活动中所获得的见解不能彼此满足。</span>
		</p>
		<p class="docText">
				<span class="docEmphStrong">Design a portion of the software system to reflect the domain model in a very literal way, so that mapping is obvious. Revisit the model and modify it to be implemented more naturally in software, even as you seek to make it reflect deeper insight into the domain. Demand a single model that serves both purposes well, in addition to supporting a robust <span class="docEmphSmaller">UBIQUITOUS LANGUAGE</span></span>.</p>
		<p class="docText">
				<span class="docEmphStrong">Draw from the model the terminology used in the design and the basic assignment of responsibilities. The code becomes an expression of the model, so a change to the code may be a change to the model. Its effect must ripple through the rest of the project's activities accordingly.</span>
		</p>
		<p class="docText">
				<span class="docEmphStrong">To tie the implementation slavishly to a model usually requires software development tools and languages that support a modeling paradigm, such as object-oriented programming.</span>
		</p>
		<p>
				<span class="docEmphStrong">        以书面的形式设计软件系统的一部分，进而与域模型相映射，这样双方的对应关系将会变得明显。重新考虑这些模型并且通过修改让他们在软件当中显得更加自然，甚至是当你在寻求一种方法，来让模型更加深刻的反映问题域的时候也要如此。追求尽可能简单的模型，让它能够满足多方面目的（软件方面和设计方面？），又能够支持足够健全的通用语言。</span>
		</p>
		<p>
				<span class="docEmphStrong">        从模型中提取那些在存在于设计中，以及存在于（域专家的?）职责所包含的基本工作中的那些术语。代码会因此成为对于模型的一种描述，所以对于代码的更改或许就是源自于对于模型的更改。从而，它们的影响将会波及到项目其他部分的行为。<br />        要牢固的把实现和模型绑定在一起，通常需要一些软件设计工具以及支持模型范例的语言，例如面向对象程序设计。<br />        </span>
		</p>
		<p class="docText">
				<span class="docEmphStrong">If the people who write the code do not feel responsible for the model, or don't understand how to make the model work for an application, then the model has nothing to do with the software. If developers don't realize that changing code changes the model, then their refactoring will weaken the model rather than strengthen it. Meanwhile, when a modeler is separated from the implementation process, he or she never acquires, or quickly loses, a feel for the constraints of implementation. The basic constraint of <span class="docEmphSmaller">MODEL-DRIVEN DESIGN</span>—that the model supports an effective implementation and abstracts key domain knowledge—is half-gone, and the resulting models will be impractical. Finally, the knowledge and skills of experienced designers won't be transferred to other developers if the division of labor prevents the kind of collaboration that conveys the subtleties of coding a <span class="docEmphSmaller">MODEL-DRIVEN DESIGN</span></span>.<br />        如果写代码的那些人对于模型没有责任感的话，或者他们并不能懂得如何让模型作用于应用，那么模型对于软件来讲毫无用处。如果开发人员不能够认识到对于代码的修改就是对于模型的修改的话，它们的重构将会使模型变得更糟，而不是让它们更加健壮。同时，当一个从事建模的人与实现过程相隔离的时候，他（她）永远也不会获得，或者说会很快失去对于实现的约束感。模型驱动设计的基本约束即是--模型需要对那些有效的（程序）实现提供支持，并且能够抽象关键的域知识--任缺其一，模型都会变得不切实际。最后，如果项目中的分工阻止了能够微妙的改善模型驱动设计代码编写的那些协作，那么团队中经验丰富的设计人员的知识和技术将不能给的其他设计人员带来提高。<br /></p>
		<p class="docText">
				<span class="docEmphStrong">Any technical person contributing to the model must spend some time touching the code, whatever primary role he or she plays on the project. Anyone responsible for changing code must learn to express a model through the code. Every developer must be involved in some level of discussion about the model and have contact with domain experts. Those who contribute in different ways must consciously engage those who touch the code in a dynamic exchange of model ideas through the <span class="docEmphSmaller">UBIQUITOUS LANGUAGE</span></span>.<br />        任何专注于模型的技术人员必须花时间接触代码，而不论他（她）在项目中的首要角色是什么。任何负责修改代码的人必须学会通过代码来描述模型。每一个开发人员必须不同程度的被纳入到对模型的讨论以及和域专家的交流中。那些上述工作之外所涉及的项目人员必须自觉地让那些接触代码的人通过通用语言动态的交换对于模型的意见。</p>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/11903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2006-08-31 23:22 <a href="http://www.cppblog.com/qzb2006e/archive/2006/08/31/11903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Domain-Driven Design: Tackling Complexity in the Heart of Software 语句精摘.2.</title><link>http://www.cppblog.com/qzb2006e/archive/2006/08/29/11834.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Tue, 29 Aug 2006 13:25:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2006/08/29/11834.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/11834.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2006/08/29/11834.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/11834.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/11834.html</trackback:ping><description><![CDATA[
		<p>Chapter Two. Communication and the Use of Language</p>
		<p>A project faces serious problems when its language is fractured. Domain experts use their </p>
		<p>jargon while technical team members have their own language tuned for discussing the domain </p>
		<p>in terms of design.</p>
		<p>The terminology of day-to-day discussions is disconnected from the terminology embedded in </p>
		<p>the code (ultimately the most important product of a software project). And even the same </p>
		<p>person uses different language in speech and in writing, so that the most incisive </p>
		<p>expressions of the domain often emerge in a transient form that is never captured in the </p>
		<p>code or even in writing.</p>
		<p>Translation blunts communication and makes knowledge crunching anemic.</p>
		<p>Yet none of these dialects can be a common language because none serves all needs.</p>
		<p>         当用于交流的语言出现断层的时候，项目将会面临一系列严重的问题。域专家们与技术团队自</p>
		<p>说自话。<br />        日常讨论所用的术语不再与代码（它们会成为软件项目的重要部分）中的术语相联系。甚至同</p>
		<p>一个人会在交流中和在记录中所用的术语不相一致，以至于问题域中那些重要的表达方式出现得如此短</p>
		<p>暂进而使它们无法被捕获到代码中去甚至无法被记录下来。</p>
		<p>Use the model as the backbone of a language. Commit the team to exercising that language </p>
		<p>relentlessly in all communication within the team and in the code. Use the same language in </p>
		<p>diagrams, writing, and especially speech.</p>
		<p>Iron out difficulties by experimenting with alternative expressions, which reflect </p>
		<p>alternative models. Then refactor the code, renaming classes, methods, and modules to </p>
		<p>conform to the new model. Resolve confusion over terms in conversation, in just the way we </p>
		<p>come to agree on the meaning of ordinary words.</p>
		<p>Recognize that a change in the UBIQUITOUS LANGUAGE is a change to the model.</p>
		<p>Domain experts should object to terms or structures that are awkward or inadequate to </p>
		<p>convey domain understanding; developers should watch for ambiguity or inconsistency that </p>
		<p>will trip up design.<br />        把模型作为通用语言的核心。推动整个团队在各种各样的交流中以及在编码中严格的实践这种</p>
		<p>语言。在图表、记录特别是谈话中统一交流方式。<br />        通过选择性的表达方式，即那些对应不同模型的表达方式来消除通用语言中的难点。然后重构</p>
		<p>代码，重新命名那些类、方法模块，使它们和新的模型相一致。我们对那些常用词汇的理解渐渐的达成</p>
		<p>一致，并以此来解决交谈期间的那些混淆。<br />        要知道，对于通用语言的任何变化都是对模型的变化。<br />       域专家们应当积极反对那些尴尬的或者不能充分传达域概念的术语，开发者应当时时留意含义不</p>
		<p>明确或者有矛盾的地方，这些地方会给设计埋下隐患。<br />Play with the model as you talk about the system. Describe scenarios out loud using the </p>
		<p>elements and interactions of the model, combining concepts in ways allowed by the model. </p>
		<p>Find easier ways to say what you need to say, and then take those new ideas back down to </p>
		<p>the diagrams and code.<br />        当你谈论系统的时候，多多使用模型。大声地使用模型所提供的那些元素和交互方式描述情节</p>
		<p>，以模型所接受的方式联结域中的概念。尽可能简单的表达你所要表达的东西，然后反过头来把这些思</p>
		<p>路转变为图表和代码。<br /></p>
<img src ="http://www.cppblog.com/qzb2006e/aggbug/11834.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2006-08-29 21:25 <a href="http://www.cppblog.com/qzb2006e/archive/2006/08/29/11834.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Domain-Driven Design: Tackling Complexity in the Heart of Software 语句精摘.1.</title><link>http://www.cppblog.com/qzb2006e/archive/2006/08/21/11539.html</link><dc:creator>littlegai</dc:creator><author>littlegai</author><pubDate>Mon, 21 Aug 2006 12:50:00 GMT</pubDate><guid>http://www.cppblog.com/qzb2006e/archive/2006/08/21/11539.html</guid><wfw:comment>http://www.cppblog.com/qzb2006e/comments/11539.html</wfw:comment><comments>http://www.cppblog.com/qzb2006e/archive/2006/08/21/11539.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/qzb2006e/comments/commentRss/11539.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/qzb2006e/services/trackbacks/11539.html</trackback:ping><description><![CDATA[Part I: Putting the Domain Model to Work<br />A domain model is not a particular diagram; it is the idea that the diagram is intended to convey. It is not just the knowledge in a domain expert's head; <span class="docEmphasis">it is a rigorously organized and selective abstraction of that knowledge</span>. A diagram can represent and communicate a model, as can carefully written code, as can an English sentence.<br />域模型并非一种特殊的图，却是这种图所要传达的含义。它并不仅是域专家头脑中的知识，它是严格组织出来的，并且有选择的抽象的知识。一张图示可以展现以及表达一种模型，同样的，一段仔细斟酌的代码可以，一句英文也可以。<br />In domain-driven design, three basic uses determine the choice of a model.<br /><span class="docEmphasis">1.The model and the heart of the design shape each other</span>. <br />2.<span class="docEmphasis">The model is the backbone of a language used by all team members</span>. <br />3.<span class="docEmphasis">The model is distilled knowledge</span>. <br />在DDD中，三种基本用途决定了模型的选择。<br />1.模型和设计的核心交相辉映。<br />2.模型是所有团队成员交流方式的中心。<br />3.模型是精化后的知识。<img src ="http://www.cppblog.com/qzb2006e/aggbug/11539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/qzb2006e/" target="_blank">littlegai</a> 2006-08-21 20:50 <a href="http://www.cppblog.com/qzb2006e/archive/2006/08/21/11539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>