﻿<?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++博客-选择C/C++-随笔分类-C++语言</title><link>http://www.cppblog.com/walkspeed/category/3746.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 19:02:38 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 19:02:38 GMT</pubDate><ttl>60</ttl><item><title>boost正则表达式库简单介绍</title><link>http://www.cppblog.com/walkspeed/archive/2007/12/28/39823.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Fri, 28 Dec 2007 06:01:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/12/28/39823.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/39823.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/12/28/39823.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/39823.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/39823.html</trackback:ping><description><![CDATA[头文件 regex.hpp<br><br>常用的类<br>boost::regex 正则表达式<br><br>boost::cmatch 以char数组为容器，存储匹配返回值。<br>boost::smatch 以std::string为容器，存储匹配返回值。<br><br>boost::regex_match 匹配算法<br>boost::regex_search 查找算法<br>boost::regex_replace 替换算法<br><br>简单例子<br><br>#include &lt;iostream&gt;<br><br>#include &lt;boost/regex.hpp&gt;<br><br>int main( int argc, char* argv[] )<br>{<br>&nbsp;&nbsp; &nbsp;char *buf = "This is boost::regex example";<br><br>&nbsp;&nbsp; &nbsp;boost::regex exampleregex( "boost::regex" );<br>&nbsp;&nbsp; &nbsp;boost::cmatch result;<br><br>&nbsp;&nbsp; &nbsp;if( boost::regex_search( buf, result, exampleregex ) )<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;std::cout &lt;&lt; result.str() &lt;&lt; std::endl;<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;return 0;<br>}<br><br>注意regex.hpp的包含。要在开发工具中设置boost头文件所在位子。<br><br>
<br><img src ="http://www.cppblog.com/walkspeed/aggbug/39823.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-12-28 14:01 <a href="http://www.cppblog.com/walkspeed/archive/2007/12/28/39823.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>snmp为何用oid来唯一标识对象</title><link>http://www.cppblog.com/walkspeed/archive/2007/08/31/31297.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Fri, 31 Aug 2007 06:01:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/08/31/31297.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/31297.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/08/31/31297.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/31297.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/31297.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 要在分布式系统中找到一个对象，甚至是对象的某个实例，我们必须给他们一个唯一标识。<br>&nbsp;&nbsp;&nbsp; 可以领用UUID来生成我们需要的唯一标识。但是在snmp中并没有选着UUID来标识每个对象，而是使用<br>了自己设计的Oid。这是为何呢？本人认为，UUID虽可以唯一表示对象及其实例，但是UUID之间没有什么<br>关系，不能形成一种结构来表示对象之间的关系。而Oid的显现却能满足以上两点，唯一表示对象和显示<br>对象之间的结构，甚至是对象的实例的唯一标识和实例之间的关系。<br>&nbsp;&nbsp;&nbsp; 这也给我们一个启示，分布式系统中对象的标识除了具有唯一性外，要有一定显示对象之间关系的能<br>力，会更好。<br><img src ="http://www.cppblog.com/walkspeed/aggbug/31297.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-08-31 14:01 <a href="http://www.cppblog.com/walkspeed/archive/2007/08/31/31297.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>接口设计的要点（接口不应被使用者直接销毁）</title><link>http://www.cppblog.com/walkspeed/archive/2007/08/07/29457.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Tue, 07 Aug 2007 01:49:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/08/07/29457.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/29457.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/08/07/29457.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/29457.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/29457.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 接口的使用者不应该在使用完接口后直接销毁接口，而应该将接口返还给接口提供者。接口提供者来管理接口的声明周期。&nbsp;&nbsp;<a href='http://www.cppblog.com/walkspeed/archive/2007/08/07/29457.html'>阅读全文</a><img src ="http://www.cppblog.com/walkspeed/aggbug/29457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-08-07 09:49 <a href="http://www.cppblog.com/walkspeed/archive/2007/08/07/29457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost.Bind的基础使用</title><link>http://www.cppblog.com/walkspeed/archive/2007/07/20/28448.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Fri, 20 Jul 2007 09:15:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/07/20/28448.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/28448.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/07/20/28448.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/28448.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/28448.html</trackback:ping><description><![CDATA[当我们使用函数时习惯于C函数的格式,即如下形式<br>resulttype funname( arglist );<br>返回值类型 函数名( 参数列表 );<br><br>在Boost.Function中，我们可以方便的定义定义函数对象。不过在定义用来表示类成员函数的函数对象时<br>第一个参数是类指针。而且在调用时，要传入一个类实例的指针。这样用起来并不是很方便，因为调用者<br>要知道类实例。这实际上没有实现解耦。而解耦是我们使用回调或委托设计的一个目标。<br><br>为了解决这个问题，我们要使用Boost.Bind库<br><br>Boost.Bind是一个函数对象工厂。他用来产生我们需要的函数对象。好了，有了它，你可以在你设计中大<br>量使用Boost.Function。不用再去定义类成员函数形式的函数对象啦，只用定义普通函数对象。<br><br>一个简单的例子<br><br>class CExample<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; bool printstr( const std::string &amp;str )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "CExample::printstr" &lt;&lt; str &lt;&lt; std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>&nbsp;&nbsp;&nbsp; }<br>};<br><br>//定义一个函数对象<br>boost::function&lt; bool ( const std::string&amp; ) &gt; printstr;<br><br>//用Boost.Bind创建一个函数对象，赋给printstr<br>CExample example;<br>printstr = boost::bind( &amp;CExample::printstr, &amp;example, _1 );<br><br>好了，我们创建了一个函数对象，而且调用时不再需要类实例拉。用Boost.Function和Boost.Bind大大<br>的简化了Command模式的实现。<br><br>在上面的例子中要个古怪的对象"_1"。这个叫做站位符，他代表这个位置有个参数，但现在还不知道参<br>数是什么。_1代表参数列表中的第一个位置上的参数。Boost.Bind一共定义了9个站位符对象。如下<br>_1,_2,_3,_4,_5,_6,_7,_8,_9。分别代表参数列表中位子。<br><br>Boost.Bind产生的函数对象可以直接使用，利用上面的例子。<br><br>bool b = boost::bind( &amp;CExample::printstr, &amp;example, _1 )( "Hello World" );<br><br><br> <img src ="http://www.cppblog.com/walkspeed/aggbug/28448.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-07-20 17:15 <a href="http://www.cppblog.com/walkspeed/archive/2007/07/20/28448.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost.Function的基本使用</title><link>http://www.cppblog.com/walkspeed/archive/2007/07/18/28272.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 18 Jul 2007 05:28:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/07/18/28272.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/28272.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/07/18/28272.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/28272.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/28272.html</trackback:ping><description><![CDATA[Boost.Function库用来提供一个对象化的函数指针。<br><br>函数指针对设计很有用。它使调用者可以延期调用，调用时机由调用者确定。而且可以改变<br>响应者，以应对不同的要求。<br><br>C中的函数指针只能用于自由函数。在C++中除了自由函数还有函数对象和类成员函数，这些<br>C的函数指针是无法用的。这要求能适应C++语言的函数指针。既然C++语言本身没有提供，<br>那就提供一个库。stl提供了，但是定义了很多类型，使用起来并不是很方便，而且函数参数<br>的个数被限定在两个以下，更能是备受限制。Boost.Function库提供了一个好的解决方案。<br><br>Boost.Function库可以支持自由函数，函数对象，类成员函数。而且参数个数多达10个。<br>Boost.Function库利用模板技术来实现。生成的代码有很高的运行效率。本库可以不用编译<br>直接使用。<br><br>Boost.Function的头文件。<br>function.hpp<br><br>定义一个Boost.Function的对象（是一个返回值类型为int，第一个参数是std::string类型<br>第二个参数是float类新）<br><br>boost::function&lt; int ( std::string, float ) &gt; funptr;<br><br>上面这个定义方式是一种容易理解的定义方式。但有些编译器不支持，如果想更多的编译器<br>支持，则用下面这种定义方式<br><br>boost::function2&lt; int, std::string, float &gt; funptr;<br><br>注意模板中有3个类型，而function类却是boost::function2。应为返回值类型不计算在参数<br>类型中（原因很简单，C++的编译器不会根据返回类型不同来区分函数定义的不同）。<br><br>int freefun( std::string str, float f )<br>{<br>&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; str &lt;&lt; " : " &lt;&lt; f &lt;&lt; std::endl;<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>class CFun<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; int operator() ( std::string str, float f )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; str &lt;&lt; " : " &lt;&lt; f &lt;&lt; std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;&nbsp; <br>&nbsp;&nbsp;&nbsp; }<br>}<br><br>上面定义了一个自由函数和一个函数对象。下面将把他们付给function对象。<br><br>赋值为自由函数<br>funptr = &amp;freefun;<br><br>赋值为函数对象<br>CFun fun;<br>funptr = fun;<br><br>以上两种情况的调用方法一致，如下<br>funptr( "float =", 10.0 );<br><br>Boost.Function对象要能指向类型原函数，其定义要如下<br><br>class FreeClass<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; int out( std::string str, float f )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; str &lt;&lt; " : " &lt;&lt; f &lt;&lt; std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;&nbsp; <br>&nbsp;&nbsp;&nbsp; }<br>};<br><br>boost::function&lt; int ( FreeClass*, std::string, float ) &gt; funptr;<br><br>跨平台的定义方法<br>boost::function3&lt; int, FreeClass*, std::string, float &gt; funptr;<br><br>赋值方法<br>funptr = &amp;FreeClass::out;<br><br>调用方法<br>FreeClass fc;<br><br>funptr( &amp;fc, "float =", 10.0 );<br><br><br> <img src ="http://www.cppblog.com/walkspeed/aggbug/28272.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-07-18 13:28 <a href="http://www.cppblog.com/walkspeed/archive/2007/07/18/28272.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>领域分析--认识领域分析</title><link>http://www.cppblog.com/walkspeed/archive/2007/07/11/27869.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 11 Jul 2007 07:54:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/07/11/27869.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/27869.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/07/11/27869.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/27869.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/27869.html</trackback:ping><description><![CDATA[领域分析--认识领域分析<br><br>软件分析的开端一般是需求分析。但是在实践中，发现了很多的问题。<br>1 用户的需求并不是有用户提出。在和用户或软件的风险承担者交谈后，会常发现，他们对自己想要的<br>软件并不是很清楚，会提出一些笼统的要求。在开发出一个原型后，他们会修正或更改，甚至推翻他们<br>的需求。你会发现是你在不断的提出、完善需求，用户或风险承担者只是在裁决你的需求。而这样下去<br>你的软件要不断的改，好像遥遥无期。<br>2 需求多是一种功能的集合。软件出来后，如果有了改动，或在新的项目中去复用以前的软件会发现很<br>难。对每个需求，你不得不从头开始。<br><br>领域分析和需求分析不同，它不是面向功能的。而是面向问题的。这有些像考试中解题。针对特定的问<br>题，来提供解决方案，并在这个方案的直接指导下解出题目。这个直接指导很有意义，应为直接指导表<br>示解题的方案将被应用到解题的过程中（即是可实现的）。<br><br>领域分析不是对要构造的软件进行全面的分析。而是对软件涉及到的特定的领域进行分析（如写多媒体<br>软件，你要对音视频领域进行分析）。而领域是与特定的知识相关联的（如音视频领域中关于音频、视<br>频编解码知识，领域分析要搞清楚这个领域中的知识，找出各知识点中的关系，并对它们进行抽象，形<br>成模型。领域分析强调的是问题域。这就是说它面对的是一个相对确定的范围。软件要解决的是一个相<br>对确定的范围。也有利于测试软件。<br><br>领域分析不能代替需求分析，但是可以脱离需求来对特定的领域进行分析。领域分析后产生的设计要直<br>接指导实现，可以映射到软件中。由于领域分析是面对问题的，它产生的软件不一定能满足需求，可能<br>根本就对应不上需求。但是它是特定问题的解决方案，可以作为一个机制来支持需求的实现。而且特定<br>的问题或着说这种反应某个领域中的知识关系的软件其对应的是一种稳定的需求，比较容易复用、测试<br>和发展。<br><br>面对需求分析得到是一种应用的要求。而根据软件涉及的领域进行分析，得到的是它的基本机制。应用<br>是多样的，而机制其实就只有那么几个。根据应用的要求来组合这些机制。这样需求的变化，并不会去<br>过多的冲击你通过领域分析得到的模型和实现。你要做的是对他们进行组合。<img src ="http://www.cppblog.com/walkspeed/aggbug/27869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-07-11 15:54 <a href="http://www.cppblog.com/walkspeed/archive/2007/07/11/27869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内存泄露和对象泄露</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/31/25180.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Thu, 31 May 2007 02:50:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/31/25180.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/25180.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/31/25180.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/25180.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/25180.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; new出来的空间如果没有主动销毁，在程序退出时仍可能有内存的泄露。<br>操作系统描述到，在进程退出时会销毁它所使用的所有内存空间，但这只是<br>一个模型上的构想和描述。在实际的操作系统的实现上并不能做到这一点。<br>因为，要实现在进程退出时销毁它所使用的内存空间，就要给每个被使用的<br>内存空间打一个标，表示这段内存空间被那个进程使用。在这种情况下，如<br>果有多个使用小内存量的进程，并且被频繁的创建和销毁，那么光记住那些<br>进程标致就要占用很大的内存空间，这是一个很不划算的方案。所以在实际<br>中，操作系统并没有给每个进程使用的内存空间打标。这样，有些小内存是<br>没有被回收的，如果多次开关这个程序就会发现，有内存被大量的占用，而<br>不能被释放。<br>&nbsp;&nbsp;&nbsp; 所以那些在程序中只有一个实例，并且是被new出来的对象，也应该主动<br>的去手动销毁，而不能依赖程序退出时由系统销毁。<br><br>&nbsp;&nbsp;&nbsp; 被new出来的对象其销毁是两个步骤。<br>&nbsp;&nbsp; &nbsp;1 析构对象。条用对象的析构函数，将对象占用的资源释放掉。<br>&nbsp;&nbsp; &nbsp;2 释放内存。将对象所占用的内存释放掉。<br>&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp; 如果new出来的对象没有被销毁，会造成连个层面上的泄露。<br>&nbsp;&nbsp;&nbsp; 1 对象泄露。他会造成背对象占用的资源也没有销毁或释放。比如在对象<br>中占有文件的句柄，在析构时才释放。如果对象泄露了，这个句柄是不会被释<br>放的。那个文件会一直被占用。如果文件打开时是独占的，那么及时对象所在<br>的程序退出了，别的程序也别想访问这个文件。<br>&nbsp;&nbsp;&nbsp; 2 内存泄露。所占用的内存不能被释放。 <br><br><img src ="http://www.cppblog.com/walkspeed/aggbug/25180.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-31 10:50 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/31/25180.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Berkeley DB在Queue模式下的使用2</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/30/25117.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 30 May 2007 05:58:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/30/25117.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/25117.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/30/25117.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/25117.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/25117.html</trackback:ping><description><![CDATA[Berkeley DB在Queue模式下的使用<br><br>Queue模式读数据的一个简单的示例<br>在Queue模式下读数据，记录（Dbt）要调用set_ulen函数和set_flags函数<br><br>#include &lt; time.h &gt;<br>#include &lt; iostream &gt;<br>#include &lt; bdb/db_cxx.h &gt;<br><br>struct ValueType<br>{<br>&nbsp;&nbsp;&nbsp; int _int;<br>&nbsp;&nbsp;&nbsp; char _char;<br>&nbsp;&nbsp;&nbsp; char _array[256];<br>};<br><br>void readDB( void )<br>{<br>&nbsp;&nbsp; &nbsp;Db bdb( 0, 0 );<br><br>&nbsp;&nbsp; &nbsp;bdb.set_re_len( sizeof( ValueType ) ); //用Queue模式一定要调用，而且一定要在open前调用<br>&nbsp;&nbsp; &nbsp;bdb.set_re_pad( 0x00 ); //为了字符串的填充为0。<br><br>&nbsp;&nbsp; &nbsp;bdb.open( 0, "SaveRecodeDB.db", 0, DB_QUEUE, DB_CREATE, 0 );<br><br>&nbsp;&nbsp; &nbsp;size_t k;<br>&nbsp;&nbsp; &nbsp;ValueType v;<br>&nbsp;&nbsp; &nbsp;Dbt key( &amp;k, sizeof( size_t ) );<br>&nbsp;&nbsp; &nbsp;key.set_ulen( sizeof( size_t ) );<br><br>&nbsp;&nbsp; &nbsp;Dbt value( &amp;v, sizeof( ValueType ) );<br>&nbsp;&nbsp; &nbsp;value.set_ulen( sizeof( ValueType ) );<br>&nbsp;&nbsp; &nbsp;value.set_flags( DB_DBT_USERMEM );<br><br>&nbsp;&nbsp; &nbsp;//直接用数据库的读函数<br>&nbsp;&nbsp; &nbsp;for( int i=0; i&lt;1000000; ++i )<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;bdb.get( 0, &amp;key, &amp;value, DB_CONSUME );<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;bdb.close( 0 );<br>}<br><br>int main( int argc, char* argv[] )<br>{<br>&nbsp;&nbsp;&nbsp; clock_t et1 = clock();<br>&nbsp;&nbsp;&nbsp; readDB();<br>&nbsp;&nbsp;&nbsp; clock_t et2 = clock();<br><br>&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "work is fine, " &lt;&lt; "have times : " &lt;&lt; et2 - et1 &lt;&lt; std::endl;<br>&nbsp;&nbsp;&nbsp; return 0;<br>}&nbsp;
<br> <img src ="http://www.cppblog.com/walkspeed/aggbug/25117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-30 13:58 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/30/25117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Berkeley DB在Queue模式下的使用 1</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/29/25089.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Tue, 29 May 2007 10:03:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/29/25089.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/25089.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/29/25089.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/25089.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/25089.html</trackback:ping><description><![CDATA[Berkeley DB在Queue模式下的使用<br><br>Queue模式下仅能存储定长的记录，既value的长度为定长。Queue的key是一个逻辑增长的数，一般就是int。<br>不需要开发者去改变这个类型。<br><br>Queue模式下只能存储定长的记录。所以一定要调用DB的set_re_length函数来设定数据库中记录的长度。<br>如果没有设定，默认的为0。这样当存储记录时一定会报异常。程序出错。<br>在读取记录时，当记录的长度小于设定的长度时，会填充字符达到设定长度。<br>默认的字符为0x02（ASCII中的）。可以设定自己的填充字符。调用DB的set_re_pad。<br><br>一个简单的示例<br><br>#include &lt; time.h &gt;<br>#include &lt; iostream &gt;<br>#include &lt; bdb/db_cxx.h &gt;<br><br>struct ValueType<br>{<br>&nbsp;&nbsp; &nbsp;int _int;<br>&nbsp;&nbsp; &nbsp;char _char;<br>&nbsp;&nbsp; &nbsp;char _array[256];<br>};<br><br>void writeDB( void )<br>{<br>&nbsp;&nbsp; &nbsp;Db bdb( 0, 0 );<br><br>&nbsp;&nbsp; &nbsp;bdb.set_re_len( sizeof( ValueType ) ); //用Queue模式一定要调用，而且一定要在open前调用<br>&nbsp;&nbsp; &nbsp;bdb.set_re_pad( 0x00 ); //为了字符串的填充为0。<br><br>&nbsp;&nbsp; &nbsp;bdb.open( 0, "SaveRecodeDB.db", 0, DB_QUEUE, DB_CREATE, 0 );<br><br>&nbsp;&nbsp; &nbsp;size_t k;<br>&nbsp;&nbsp; &nbsp;ValueType v;<br>&nbsp;&nbsp; &nbsp;Dbt key( &amp;k, sizeof( size_t ) );<br>&nbsp;&nbsp; &nbsp;Dbt value( &amp;v, sizeof( ValueType ) );<br><br>&nbsp;&nbsp; &nbsp;//直接用数据库的写函数<br>&nbsp;&nbsp; &nbsp;for( int i=0; i&lt;1000000; ++i )<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;bdb.put( 0, &amp;key, &amp;value, DB_APPEND );<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;bdb.close( 0 );<br>}<br><br>int main( int argc, char* argv[] )<br>{<br>&nbsp;&nbsp; &nbsp;clock_t et1 = clock();<br>&nbsp;&nbsp; &nbsp;writeDB();<br>&nbsp;&nbsp; &nbsp;clock_t et2 = clock();<br><br>&nbsp;&nbsp; &nbsp;std::cout &lt;&lt; "work is fine, " &lt;&lt; "have times : " &lt;&lt; et2 - et1 &lt;&lt; std::endl;<br>&nbsp;&nbsp; &nbsp;return 0;<br>}
<br><br>在Queue模式下不能用游标进行数据的插入。只能进行数据的修改。<br>&nbsp;<br>&nbsp;<br>  <img src ="http://www.cppblog.com/walkspeed/aggbug/25089.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-29 18:03 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/29/25089.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Berkeley DB对并发的支持</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/26/24892.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Sat, 26 May 2007 08:17:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/26/24892.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/24892.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/26/24892.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/24892.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/24892.html</trackback:ping><description><![CDATA[Berkeley DB对并发的支持<br><br>要让Berkeley DB数据支持并发，就要创建Berkeley DB的环境（environment）<br>环境类是 DbEnv。要支持并发，在初始化DbEnv时要用DB_INIT_CDB、DB_INIT_MPOOL<br>两个标致。<br><br>如下<br><br>DbEnv env；<br>env.open( "evn", DB_INIT_CDB|DB_INIT_MPOOL, 0 );<br><br>然后在创建数据库时，将环境传给数据库。如下<br><br>Db bdb( &amp;env, 0 );<br><br>这样就可以支持并发了。<br><br>Berkeley DB并发的简单原则<br>Berkeley DB的并发遵循的是允许同时多个读操作，当只有一个写操作。<br>1 每个游标有一锁，非游标的读写用一锁<br>2 写操作等待所有的读锁解锁。<br>3 读操作不需要等待写锁解锁。
<br>  <img src ="http://www.cppblog.com/walkspeed/aggbug/24892.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-26 16:17 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/26/24892.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Berkeley DB的介绍</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/26/24886.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Sat, 26 May 2007 03:26:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/26/24886.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/24886.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/26/24886.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/24886.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/24886.html</trackback:ping><description><![CDATA[Berkeley DB的访问方法有四种BTree、Hash、Queue、Recno<br>他们在DB创建时选择，而且只能在创建时选择。一点选定某一个访问方法，<br>在使用中不能改变。<br><br>BTree 数据被存储在一个排序的平衡树结构中。key和value都可以是简单数<br>据（如整型，字符串），也可以是复杂数据（如结构）。当有多个数据的key<br>相同时，可以有复本。<br><br>Hash 数据存储在一个扩展的线性hash表中。其他的特性象BTree。<br><br>Queue 数据存储在一个队列中，记录是定长的。key为一个逻辑数，不由用户<br>选择类型。在尾部插入记录，在头部删除记录和取出记录非常的快。提供了<br>记录水平缩，提高在并发下的访问。<br><br>Recno 数据可以是定常或是变长的记录。其他特性象Queue。key也是一个逻辑数。<br><br>数据库访问方法的选择。<br>根据key可否用户定义分为BTree、Hash一组，Queue、Renco一组。<br><br>BTree与Hash之间的选择<br>如果数据量不，能被放到内存中。这种情况下选择BTree。即在小数据量的情况下<br>选用BTree，原因是在利用key来定为记录时，成功的几率大些。Hash有退步算法。<br><br>但是在大数据量的情况下，由于数据并不能都在数据库中，要访问磁盘，并且BTree<br>要维护的内部信息大于Hash，访问磁盘的几率大于Hash，会造成访问的瓶颈。所以<br>在大数据量下选择Hash。<br><br>Queue与Recno之间的选择<br>用在多并发下最好用Queue。但是如果记录是变长的，就只能选Recno了。在其它的情<br>况下，两者没有明显的差别。<br><br>Berkeley DB支持从非常小的数据库到256T的数据容量的数据库。单个key或recode<br>最大可以为4G的数据。<br><br>Berkeley DB的数据库被存储为二进制的格式，有利于平台的移植。<br><br>Berkeley DB支持并发的访问，但是不能用在NSF（网络文件系统）下。因为无法定位和<br>获得数据库的环境（在环境中设置对并发的控制）。<br><br>Berkeley DB的环境（Environments）提供了以下的功能<br>1 多数据库文件（Multi-database files）。将多个数据存储在一个物理文件中。<br>2 提供多线程或多进程的支持（Multi-thread and multi-process support）。<br>3 事务处理<br>4 高可用性（重复性）支持。即一个主数据库，和多个提供只读能力的复制数据库<br>5 日志子系统。
<br> <img src ="http://www.cppblog.com/walkspeed/aggbug/24886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-26 11:26 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/26/24886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++标准库中用来计算时间差的函数 C++标准库用来格式化输出时间字符串</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/25/24831.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Fri, 25 May 2007 07:30:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/25/24831.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/24831.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/25/24831.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/24831.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/24831.html</trackback:ping><description><![CDATA[C++标准库中用来计算时间差的函数<br>头文件 &lt; time.h &gt;<br><br>double difftime( <br>&nbsp;&nbsp; time_t timer1,<br>&nbsp;&nbsp; time_t timer0 <br>);<br>double _difftime32( <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __time32_t timer1,<br>&nbsp;&nbsp; __time32_t timer0 <br>);<br>double _difftime64( <br>&nbsp;&nbsp; __time64_t timer1,<br>&nbsp;&nbsp; __time64_t timer0 <br>);<br><br>C++标准库用来格式化输出时间字符串<br>头文件 &lt; time.h &gt;<br><br>size_t strftime(<br>&nbsp;&nbsp; char *strDest,<br>&nbsp;&nbsp; size_t maxsize,<br>&nbsp;&nbsp; const char *format,<br>&nbsp;&nbsp; const struct tm *timeptr <br>);<br>size_t _strftime_l(<br>&nbsp;&nbsp; char *strDest,<br>&nbsp;&nbsp; size_t maxsize,<br>&nbsp;&nbsp; const char *format,<br>&nbsp;&nbsp; const struct tm *timeptr,<br>&nbsp;&nbsp; _locale_t locale<br>);<br>size_t wcsftime(<br>&nbsp;&nbsp; wchar_t *strDest,<br>&nbsp;&nbsp; size_t maxsize,<br>&nbsp;&nbsp; const wchar_t *format,<br>&nbsp;&nbsp; const struct tm *timeptr <br>);<br>size_t _wcsftime_l(<br>&nbsp;&nbsp; wchar_t *strDest,<br>&nbsp;&nbsp; size_t maxsize,<br>&nbsp;&nbsp; const wchar_t *format,<br>&nbsp;&nbsp; const struct tm *timeptr,<br>&nbsp;&nbsp; _locale_t locale<br>);<br><br>The formatting codes for strftime are listed below:<br><br>%a<br>&nbsp;&nbsp;&nbsp; Abbreviated weekday name<br><br>%A<br>&nbsp;&nbsp;&nbsp; Full weekday name<br><br>%b<br>&nbsp;&nbsp;&nbsp; Abbreviated month name<br><br>%B<br>&nbsp;&nbsp;&nbsp; Full month name<br><br>%c<br>&nbsp;&nbsp;&nbsp; Date and time representation appropriate for locale<br><br>%d<br>&nbsp;&nbsp;&nbsp; Day of month as decimal number (01 &#8211; 31)<br><br>%H<br>&nbsp;&nbsp;&nbsp; Hour in 24-hour format (00 &#8211; 23)<br><br>%I<br>&nbsp;&nbsp;&nbsp; Hour in 12-hour format (01 &#8211; 12)<br><br>%j<br>&nbsp;&nbsp;&nbsp; Day of year as decimal number (001 &#8211; 366)<br><br>%m<br>&nbsp;&nbsp;&nbsp; Month as decimal number (01 &#8211; 12)<br><br>%M<br>&nbsp;&nbsp;&nbsp; Minute as decimal number (00 &#8211; 59)<br><br>%p<br>&nbsp;&nbsp;&nbsp; Current locale's A.M./P.M. indicator for 12-hour clock<br><br>%S<br>&nbsp;&nbsp;&nbsp; Second as decimal number (00 &#8211; 59)<br><br>%U<br>&nbsp;&nbsp;&nbsp; Week of year as decimal number, with Sunday as first day of week (00 &#8211; 53)<br><br>%w<br>&nbsp;&nbsp;&nbsp; Weekday as decimal number (0 &#8211; 6; Sunday is 0)<br><br>%W<br>&nbsp;&nbsp;&nbsp; Week of year as decimal number, with Monday as first day of week (00 &#8211; 53)<br><br>%x<br>&nbsp;&nbsp;&nbsp; Date representation for current locale<br><br>%X<br>&nbsp;&nbsp;&nbsp; Time representation for current locale<br><br>%y<br>&nbsp;&nbsp;&nbsp; Year without century, as decimal number (00 &#8211; 99)<br><br>%Y<br>&nbsp;&nbsp;&nbsp; Year with century, as decimal number<br><br>%z, %Z<br>&nbsp;&nbsp;&nbsp; Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown<br><br>%%<br>&nbsp;&nbsp;&nbsp; Percent sign
<br><img src ="http://www.cppblog.com/walkspeed/aggbug/24831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-25 15:30 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/25/24831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++标准库中string类使用的注意。</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/25/24825.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Fri, 25 May 2007 06:47:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/25/24825.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/24825.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/25/24825.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/24825.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/24825.html</trackback:ping><description><![CDATA[C++标准库中string类使用的注意。<br><br>在string类之间进行复制没有什么问题。<br>但是要拷贝到内存中时就要注意。一定要在string取出的长度上加1。<br><br>如下<br><br>char buf[256];<br>std::string str = "1234567890";<br><br>memcpy( buf, str.c_str(), str.length()+1 );<br><br>这样才能拷贝到字符串的结束符&#8216;0&#8217;。要不就拷贝不到。<br>string的length函数只计算有效字符的长度。如同C中的strlen函数。
<br><img src ="http://www.cppblog.com/walkspeed/aggbug/24825.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-25 14:47 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/25/24825.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在工作中对文件操作引发的想法</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/24/24764.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Thu, 24 May 2007 08:42:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/24/24764.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/24764.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/24/24764.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/24764.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/24764.html</trackback:ping><description><![CDATA[文件是一种资源。<br>流对象要依附与某个资源。<br><br>所以在C++标准库中，流都是不可拷贝的和赋值的。<br>一个类有了流对象成员，那么它也就不可拷贝和赋值了。<br>如果进行了拷贝和赋值会出现运行时错误。<br><br>这也表现了一种设计范型。<br>资源只能在资源的使用者中保存其应用。并在资源的使用者环境中创建。<br>不同使用者之间只传递资源的描述，而不直接传递资源。<br><br>例如。<br>一个类要使用文件。<br>只传递给这个类文件的描述，如文件名，偏移量等等。<br>而不传个他一个文件。<br><br>这个类再根据这些描述来开启文件。对其操作。
<br><img src ="http://www.cppblog.com/walkspeed/aggbug/24764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-24 16:42 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/24/24764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tm结构中每个字段的解释</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/23/24684.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 23 May 2007 04:02:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/23/24684.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/24684.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/23/24684.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/24684.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/24684.html</trackback:ping><description><![CDATA[tm结构中每个字段的解释<br><br>tm结构中的每个段是一个int类型<br><br>tm_sec 秒钟【0，59】<br>tm_min 分钟【0，59】<br>tm_hour 小时【0，23】。是从午夜开始计时。UTC下是是以格林威治为标准0，local下是以本地时区为标准0.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gmtime返回的是UTC，localtime返回的是本地。<br>tm_mon 月份【0，11】。注意是0到11.而不是常用的1到12.<br>tm_year 年份。是从1900年开始计算。即记录的是本年与1900年的差值。<br>tm_wday 表示在一个星期中的第几天【0，6】<br>tm_yday 表示一年中的第几天【0，365】，1月1日为0<br>tm_isdst 不清楚，文档中只是说在gmtime下为0<br><img src ="http://www.cppblog.com/walkspeed/aggbug/24684.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-23 12:02 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/23/24684.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用于时间的c的运行时函数库中的函数</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/22/24586.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Tue, 22 May 2007 02:00:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/22/24586.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/24586.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/22/24586.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/24586.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/24586.html</trackback:ping><description><![CDATA[将tm结构的值转换为一个time_t类型的值<br>在32位系统中time_t是一个long。<br>头文件 &lt;time.h&gt;<br><br>time_t mktime(<br>&nbsp;&nbsp; struct tm *timeptr <br>);<br>__time32_t _mktime32(<br>&nbsp;&nbsp; struct tm *timeptr <br>);<br>__time64_t _mktime64(<br>&nbsp;&nbsp; struct tm *timeptr <br>);<br><br>获得系统时间。<br>头文件 &lt;time.h&gt;<br>In Visual C++ 2005, time is a wrapper for _time64 and time_t is, by default, equivalent to __time64_t. <br>If you need to force the compiler to interpret time_t as the old 32-bit time_t, you can define _USE_32BIT_TIME_T. <br>This is not recommended because your application may fail after January 18, 2038; the use of this macro is not allowed on 64-bit platforms.<br><br>time_t time(<br>&nbsp;&nbsp; time_t *timer <br>);<br>__time32_t _time32(<br>&nbsp;&nbsp; __time32_t *timer <br>);<br>__time64_t _time64(<br>&nbsp;&nbsp; __time64_t *timer <br>);<br><br><br>将时间转换成一个字符串<br>头文件 &lt;time.h&gt;<br><br>char *ctime( <br>&nbsp;&nbsp; const time_t *timer <br>);<br>char *_ctime32( <br>&nbsp;&nbsp; const __time32_t *timer )<br>;<br>char *_ctime64( <br>&nbsp;&nbsp; const __time64_t *timer )<br>;<br>wchar_t *_wctime( <br>&nbsp;&nbsp; const time_t *timer <br>);<br>wchar_t *_wctime32( <br>&nbsp;&nbsp; const __time32_t *timer<br>);<br>wchar_t *_wctime64( <br>&nbsp;&nbsp; const __time64_t *timer <br>);<br><br>将时间转换成一个字符串<br>是个安全的版本，用来替代上面的函数<br>头文件 &lt;time.h&gt;<br><br>errno_t ctime_s( <br>&nbsp;&nbsp; char* buffer,<br>&nbsp;&nbsp; size_t sizeInBytes,<br>&nbsp;&nbsp; const time_t *time <br>);<br>errno_t _ctime32_s( <br>&nbsp;&nbsp; char* buffer,<br>&nbsp;&nbsp; size_t sizeInBytes,<br>&nbsp;&nbsp; const __time32_t *time <br>);<br>errno_t _ctime64_s( <br>&nbsp;&nbsp; char* buffer,<br>&nbsp;&nbsp; size_t sizeInBytes,<br>&nbsp;&nbsp; const __time64_t *time )<br>;<br>errno_t _wctime_s( <br>&nbsp;&nbsp; wchar_t* buffer,<br>&nbsp;&nbsp; size_t sizeInWords,<br>&nbsp;&nbsp; const time_t *time <br>);<br>errno_t _wctime32_s( <br>&nbsp;&nbsp; wchar_t* buffer,<br>&nbsp;&nbsp; size_t sizeInWords,<br>&nbsp;&nbsp; const __time32_t *time <br>);<br>errno_t _wctime64_s( <br>&nbsp;&nbsp; wchar_t* buffer,<br>&nbsp;&nbsp; size_t sizeInWords,<br>&nbsp;&nbsp; const __time64_t *time <br>);<br>template &lt;size_t size&gt;<br>errno_t _ctime32_s( <br>&nbsp;&nbsp; char (&amp;buffer)[size],<br>&nbsp;&nbsp; const __time32_t *time <br>); // C++ only<br>template &lt;size_t size&gt;<br>errno_t _ctime64_s( <br>&nbsp;&nbsp; char (&amp;buffer)[size],<br>&nbsp;&nbsp; const __time64_t *time<br>); // C++ only<br>template &lt;size_t size&gt;<br>errno_t _wctime32_s( <br>&nbsp;&nbsp; wchar_t (&amp;buffer)[size],<br>&nbsp;&nbsp; const __time32_t *time <br>); // C++ only<br>template &lt;size_t size&gt;<br>errno_t _wctime64_s( <br>&nbsp;&nbsp; wchar_t (&amp;buffer)[size],<br>&nbsp;&nbsp; const __time64_t *time <br>); // C++ only<br><br><br>将时间值转换成一个结构<br>头文件 &lt;time.h&gt;<br><br>struct tm *gmtime( <br>&nbsp;&nbsp; const time_t *timer <br>);<br>struct tm *_gmtime32( <br>&nbsp;&nbsp; const time32_t *timer <br>);<br>struct tm *_gmtime64( <br>&nbsp;&nbsp; const __time64_t *timer <br>);<br><br>将时间值转换成一个结构<br>头文件 &lt;time.h&gt;<br>同上面函数的功能，是安全版本<br><br>errno_t _gmtime_s(<br>&nbsp;&nbsp; struct tm* _tm,<br>&nbsp;&nbsp; const __time_t* time<br>);<br>errno_t _gmtime32_s(<br>&nbsp;&nbsp; struct tm* _tm,<br>&nbsp;&nbsp; const __time32_t* time<br>);<br>errno_t _gmtime64_s(<br>&nbsp;&nbsp; struct tm* _tm,<br>&nbsp;&nbsp; const __time64_t* time <br>);<br><br>将时间转换成本地时间。<br>头文件 &lt;time.h&gt;<br><br>struct tm *localtime(<br>&nbsp;&nbsp; const time_t *timer <br>);<br>struct tm *_localtime32(<br>&nbsp;&nbsp; const __time32_t *timer<br>);<br>struct tm *_localtime64(<br>&nbsp;&nbsp; const __time64_t *timer <br>);<br><br>将时间转换成本地时间。<br>头文件 &lt;time.h&gt;<br>同上面函数的功能，是安全版本<br><br>errno_t _localtime_s(<br>&nbsp;&nbsp; struct tm* _tm,<br>&nbsp;&nbsp; const time_t *time <br>);<br>errno_t _localtime32_s(<br>&nbsp;&nbsp; struct tm* _tm,<br>&nbsp;&nbsp; const time32_t *time <br>);<br>errno_t _localtime64_s(<br>&nbsp;&nbsp; struct tm* _tm,<br>&nbsp;&nbsp; const _time64_t *time <br>);<br><br>clock函数<br>头文件 &lt;time.h&gt;<br>clock_t clock( void );<br><br><br><img src ="http://www.cppblog.com/walkspeed/aggbug/24586.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-22 10:00 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/22/24586.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>输入流的读取操作中一些要小心的地方</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/20/24432.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Sun, 20 May 2007 04:06:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/20/24432.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/24432.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/20/24432.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/24432.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/24432.html</trackback:ping><description><![CDATA[输入流的读取多个字符的操作多用read。<br>read的定义形式如下<br>basic_istream&amp; read( char_type *_Str, streamsize _Count );<br><br>char_type* 是流字符类型的指针，这个指针是用来存储要读取的字符<br>的位置。<br>streamsize 是存储空间大小的类型，多位long。<br><br>重点在返回值的类型，是一个输入流类型的应用。不是实际的读取数据的长度。<br>要获得实际的读取长度要调用 gcount函数。定义如下<br>streamsize gcount( ) const;<br><br>要获得当前读取的位置要调用tellg函数。定义如下<br>pos_type tellg( );<br>想要知道以一共读取了多少数据就可以用这个函数。<br>tellg会跳过格式符。即返回的位置是跳过控制符的。<br>这就是说几个gcount的和不一定等于tellg的值。所以<br>用来确定读取位置时一定要用tellg函数。而不能用<br>gcount的和，在偏移，这会产生不对的位置。<br><br>看下面的例子<br>int main( int argc, char* argv[] )<br>{<br>&nbsp;&nbsp; &nbsp;std::ifstream ifile;<br><br>&nbsp;&nbsp; &nbsp;char buf[10];<br><br>&nbsp;&nbsp; &nbsp;ifile.open( "example.txt" ); //examplet.txt文件中每行有一个回车符<br><br>&nbsp;&nbsp; &nbsp;ifile.read( buf, 10 );<br>&nbsp;&nbsp; &nbsp;size_t size = ifile.tellg(); //size为11<br>&nbsp;&nbsp; &nbsp;size = ifile.gcount(); //size为10<br><br>&nbsp;&nbsp; &nbsp;ifile.read( buf, 10 );<br>&nbsp;&nbsp; &nbsp;size = ifile.tellg(); //size为22<br>&nbsp;&nbsp; &nbsp;size = ifile.gcount(); //size为10<br><br>&nbsp;&nbsp; &nbsp;if( ifile.eof() )<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return -1;<br>&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;ifile.close();<br><br>&nbsp;&nbsp; &nbsp;return 0;<br>}<br><br>读取过程中可能会出现问题，流是不保证读取过程的完整性。即要读多少数据，<br>在对到这么多的数据后才返回。<br>这要求编程人员去判断流的当前状态。再进行下面的处理。<br><br>good函数知道当前状态是好的。即上一个操作成功。可以进行下一个操作。<br>fail函数表示上一个操作失败。但流还没有完全破坏，可以进行一些处理。<br>bad函数表示流被破坏啦，别想了。不要在处理这个流拉。<br>eof函数表示已到流的尾部。不用再往下读拉。不会读出数据的。<br><br>int main( int argc, char* argv[] )<br>{<br>&nbsp;&nbsp; &nbsp;std::ifstream ifile;<br><br>&nbsp;&nbsp; &nbsp;char buf[10];<br><br>&nbsp;&nbsp; &nbsp;ifile.open( "example.txt" ); //examplet.txt文件中每行有一个回车符<br>&nbsp;&nbsp; &nbsp;ifile.seekg( 0, ios::end );<br>&nbsp;&nbsp; &nbsp;ifile.close();<br>&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp; ifile.open( "example.txt" );<br><br>&nbsp;&nbsp;&nbsp; //这是成立的。说明状态并没有应为文件的关闭而改变。只要这个对象<br>&nbsp;&nbsp;&nbsp; //的还活着，他的上一个状态将保持。而起会对下面的操作产生影响。<br>&nbsp;&nbsp;&nbsp; //除非你清除或修改了状态。<br>&nbsp;&nbsp;&nbsp; if( ifile.eof() ) <br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ifile.close();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ifile.close();<br><br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br>&nbsp;<br><img src ="http://www.cppblog.com/walkspeed/aggbug/24432.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-20 12:06 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/20/24432.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用WTL作界面开发3</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/09/23694.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 09 May 2007 03:59:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/09/23694.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/23694.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/09/23694.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/23694.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/23694.html</trackback:ping><description><![CDATA[WTL中的窗口消息的映射和自定义窗口消息映射<br><br>窗口消息的映射是通过宏MESSAGE_HANDLER完成的。<br>MESSAGE_HANDLER（ 消息ID，消息处理函数 ）。<br>自定义的消息也是通过这个宏来映射的<br><br>添加窗口消息函数后的对话框的定义如下<br>#include &lt; atlapp.h &gt;<br>#include "resource.h"<br><br>const int WM_MY_MESSAGE = WM_USER+1; //自定义消息ID<br><br>class CMainDialog : public CDialogImpl&lt; CMainDialog &gt;<br>{<br>public:<br>&nbsp;&nbsp; &nbsp;enum { IDD = IDD_MAINDLG };<br><br>public:<br>&nbsp;&nbsp; &nbsp;BEGIN_MSG_MAP( CMainDialog )<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog ) //系统的窗口消息映射，窗口初始化消息<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;MESSAGE_HANDLER( WM_MY_MESSAGE, OnMyMessage ) //自定义消息的映射<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;COMMAND_ID_HANDLER( IDOK, OnOk ) //控件消息的映射<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;COMMAND_ID_HANDLER( IDCANCEL, OnCancel )<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;COMMAND_ID_HANDLER( IDC_SENDMESSAGE_BUTTON, OnSendMyMessage ) //用来发送自定义消息的按钮消息映射<br>&nbsp;&nbsp; &nbsp;END_MSG_MAP()<br><br>public:<br>&nbsp;&nbsp;&nbsp; //窗口初始化消息映射函数，这是个窗口系统消息<br>&nbsp;&nbsp; &nbsp;LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&amp; bHandled)<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// center the dialog on the screen<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;CenterWindow();<br><br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return TRUE;<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;LRESULT OnOk( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &amp;bHandled )<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;EndDialog( wID );<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return 0;<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &amp;bHandled )<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;EndDialog( wID );<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return 0;<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;//发送自定义消息<br>&nbsp;&nbsp; &nbsp;LRESULT OnSendMyMessage( WORD wNotfyCode, WORD wID, HWND hWndCtl, BOOL &amp;bHandled )<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//ATL::CWindow的SendMessage的调用<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;SendMessage( WM_MY_MESSAGE );<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return 0;<br>&nbsp;&nbsp; &nbsp;}<br><br>&nbsp;&nbsp; &nbsp;//处理自定义消息<br>&nbsp;&nbsp; &nbsp;LRESULT OnMyMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&amp; bHandled )<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//ATL::CWindow的MessageBox的调用<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;MessageBox( "This is MyMessage Handle" ); //弹出个对话框<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return 0;<br>&nbsp;&nbsp; &nbsp;}<br>};
<br> <img src ="http://www.cppblog.com/walkspeed/aggbug/23694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-09 11:59 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/09/23694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用WTL作界面开发2</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/09/23690.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 09 May 2007 03:18:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/09/23690.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/23690.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/09/23690.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/23690.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/23690.html</trackback:ping><description><![CDATA[WTL创建对话框。<br>要用到头文件 atlapp.h<br><br>对话框的定义如下<br>#include &lt; atlapp.h &gt;<br>class CMainDialog : public CDialogImpl&lt; CMainDialog &gt;<br>{<br>&nbsp;&nbsp;&nbsp; //用户代码<br>}<br><br>CDialogImpl类是WTL中的模式对话框的基类。他利用了奇异自递归模板技术，来获得继承类的实际行为。<br>有了定义我们要给这个对话框一个窗口资源。很简单，只要代码中定义一个IDD的枚举量就可以了。<br>枚举量的值为窗口资源的ID。对话框的定义代码演化为如下<br>#include &lt; atlapp.h &gt;<br>class CMainDialog : public CDialogImpl&lt; CMainDialog &gt;<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; enum { IDD=IDD_MAINDLG };//一定要在public域，否则没办法访问，编译时报错<br>&nbsp;&nbsp;&nbsp; //用户代码<br>}<br><br>就这样进行编译，编译器会报错，说CMainDialog是个抽象类，不能实例化。<br>其原因是ProessWindowMessage函数是个抽象地。<br>我们是不是要手动添加这个函数呢？可以。但对于编写代码来说并不方便。<br>这里要用到ATL中的消息映射宏了。<br>BEGIN_MSG_MAP( 类名 )<br>END_MSG_MAP()<br>有了这两个宏对后，就自动的添加了ProessWindowMessage函数了，而且添加消息映射的函数也方便。<br>现在对话框的定义代码演化为如下了<br>#include &lt; atlapp.h &gt;<br>class CMainDialog : public CDialogImpl&lt; CMainDialog &gt;<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; enum { IDD=IDD_MAINDLG };//一定要在public域，否则没办法访问，编译时报错<br>&nbsp;&nbsp; &nbsp;<br>public:<br>&nbsp;&nbsp;&nbsp; BEGIN_MSG_MAP( CMainDialog )<br>&nbsp;&nbsp;&nbsp; END_MSG_MAP()<br>&nbsp;&nbsp;&nbsp; //用户代码<br>}<br><br>有了以上代码，对话框就可以显现在屏幕上了。但是这个对话框没有办法推出，应为没有一个消息映射函数。<br>接不到推出的消息。<br>我们有添加两个消息映射，分别对应界面上的OK按钮和Cancel按钮。这两个是button控件，我们用控件的消息映射<br>COMMAND_ID_HANDLER( ID, Fun )。<br>添加消息映射后的对话框类定义如下<br>#include &lt; atlapp.h &gt;<br>class CMainDialog : public CDialogImpl&lt; CMainDialog &gt;<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; enum { IDD=IDD_MAINDLG };//一定要在public域，否则没办法访问，编译时报错<br>&nbsp;&nbsp;&nbsp; <br>public:<br>&nbsp;&nbsp;&nbsp; BEGIN_MSG_MAP( CMainDialog )<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; COMMAND_ID_HANDLER( IDOK, OnOk )<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; COMMAND_ID_HANDLER( IDCANCEL, OnCancel )<br>&nbsp;&nbsp;&nbsp; END_MSG_MAP()<br>&nbsp;&nbsp;&nbsp; <br>public:<br>&nbsp;&nbsp;&nbsp; LRESULT OnOk( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &amp;bHandled )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; EndDialog( wID );//推出对话框<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &amp;bHandled )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; EndDialog( wID );//推出对话框<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; //用户代码<br>}; <br><br><img src ="http://www.cppblog.com/walkspeed/aggbug/23690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-09 11:18 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/09/23690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用WTL作界面开发1</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/09/23685.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 09 May 2007 02:42:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/09/23685.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/23685.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/09/23685.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/23685.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/23685.html</trackback:ping><description><![CDATA[程序的进入函数不是C/C++的进入函数main，而是微软的进入函数winMain。其形式如下<br>int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd )<br>{<br>&nbsp;&nbsp;&nbsp; //用户代码<br>&nbsp;&nbsp;&nbsp; ...............<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>WTL是在ATL的基础上发展起来的，要用到ATL中的模块类CComModule,所以要初始化COM库。<br>初始化COM库调用CoInitialize，卸载COM库调用CoUninitialize。程序形式如下<br>#include &lt; atlbase.h &gt; <br><br>int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd )<br>{<br>&nbsp;&nbsp;&nbsp; CoInitialize（ NULL ）;//用于应用程序<br>&nbsp;&nbsp;&nbsp; //用户代码<br>&nbsp;&nbsp;&nbsp; ...............<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; CoUninitialize（）;<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>WTL的应用程序部分的代码封装在了CAppModule中。要定义一个CAppModule的全局变量，保证在程序启动前就被构造好<br>CAppModule是继承的ATL中的CComModule类。程序形式演变成如下<br>#include &lt; atlbase.h &gt;<br>#include &lt; atlapp.h &gt; //WTL要用到的<br><br>int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd )<br>{<br>&nbsp;&nbsp;&nbsp; CoInitialize（ NULL ）;//用于应用程序<br>&nbsp;&nbsp;&nbsp; &nbsp;_Module.Init( NULL, hInstance );//初始化一个应用程序<br>&nbsp;&nbsp;&nbsp; //用户代码<br>&nbsp;&nbsp;&nbsp; ...............<br>&nbsp;&nbsp;&nbsp; _Module.Term();//销毁<br>&nbsp;&nbsp;&nbsp; CoUninitialize（）;<br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><img src ="http://www.cppblog.com/walkspeed/aggbug/23685.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-09 10:42 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/09/23685.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用C++标准库中文件流对象，如何获得文件的大小</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/02/23336.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 02 May 2007 09:04:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/02/23336.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/23336.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/02/23336.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/23336.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/23336.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; C++标准库中的文件流类提供的各种操作中没有直接获得正在操作的文件的大小的函数。要获得文件大小得转个弯，用如下的方法<br>&nbsp;&nbsp;&nbsp; 假设我们有了一个已经打开的文件对象ifile。<br>&nbsp;&nbsp;&nbsp; 先将文件内的位置指针移到文件尾<br>&nbsp;&nbsp;&nbsp; ifile.seekg( 0, ios::end );<br>&nbsp;&nbsp;&nbsp; 再读取当前位置，这就是文件的大小了。<br>&nbsp;&nbsp;&nbsp; long filelength = ifile.tellg();<br><br><img src ="http://www.cppblog.com/walkspeed/aggbug/23336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-02 17:04 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/02/23336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++标准库中文件流读取操作小结</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/02/23335.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 02 May 2007 08:57:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/02/23335.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/23335.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/02/23335.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/23335.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/23335.html</trackback:ping><description><![CDATA[通过文件流读取数据<br>ifstream类代表读文件对象，所有的读操作都在这个类中。<br><br>read成员函数，用来读取数据到指定的buf中。<br>这个成员函数来至basic_istream类。<br>函数原型（来直MSDN文档）<br>basic_istream&amp; read( char_type *_Str, streamsize _Count );<br>_Str&nbsp;&nbsp; 字符指针<br>_Count 要读取的字符数量<br><br>get成员函数，用来读取一个或多个字符<br>这个成员函数来至basic_istream类。<br>函数原型（来直MSDN文档）<br>int_type get( ); 读取一个字符，不过是作为int类型返回<br>basic_istream&amp; get( char_type&amp; _Ch ); 读取一个字符<br>basic_istream&amp; get( char_type *_Str, streamsize _Count ); 读取指定数量的字符<br>basic_istream&amp; get( char_type *_Str, streamsize _Count, char_type _Delim ); 读取指定数量的字符，但与到与_Delim相同的字符就停止<br>basic_istream&amp; get( basic_streambuf&lt;Elem, Tr&gt; *_Strbuf ); <br>basic_istream&amp; get( basic_streambuf&lt;Elem, Tr&gt; *_Strbuf, char_type _Delim );<br><br>peek成员函数，用来返回下一个字符，当不从istream的buf中移出<br>这个成员函数来至basic_istreamlei。<br>函数原型（来至MSDN文档）<br>int_type peek( );<br><br>getline成员函数，用来读取一行数据<br>这个成员函数来至basic_istream类<br>函数原型（来至MSDN文档）<br>basic_istream&amp; getline( char_type *_Str, streamsize _Count );<br>basic_istream&amp; getline( char_type *_Str, streamsize _Count, char_type _Delim );<br><br>readsome成员函数，用于读取指定数量的数据到buf中<br>这个函数来至basic_istream类。<br>函数原型（来至MSDN文档）<br>streamsize readsome( char_type *_Str, streamsize _Count );<br><br>&gt;&gt;运算符重载<br>对C++基本类型进行了重载操作。可以直接读取这些数据。但会跳过控制字符。<br>用户可以扩展这个运算符操作的类型。<br>这个读取是有类型的。<br><br>
<br><img src ="http://www.cppblog.com/walkspeed/aggbug/23335.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-02 16:57 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/02/23335.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++标准库中文件流基本操作</title><link>http://www.cppblog.com/walkspeed/archive/2007/05/02/23325.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 02 May 2007 05:31:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/05/02/23325.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/23325.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/05/02/23325.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/23325.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/23325.html</trackback:ping><description><![CDATA[C++ STL中的对文件操作的类<br>ifstream 用于读文件<br>ofstream 用于写文件<br>fstream&nbsp; 用于读写文件<br><br>打开文件<br>可以在够高文件流对象时直接打开<br>ifstream ifile( 文件名 )<br>ofstream ofile( 文件名 )<br>fstream&nbsp; file( 文件名 )<br><br>也可以用open行为<br>ifstream ifile<br>ifile.open( 文件名 )<br>ofstream ofile<br>ofile.open( 文件名 )<br>fstream file<br>file.open( 文件名 )<br><br>关闭文件<br>文件对象销毁时自动关闭文件。<br>也可用close关闭文件。<br>ifile.close()<br>ofile.close()<br>file.close()<br><br>文件大开放式标致<br>这写标致定义在iso_base类中。分别如下<br>in&nbsp;&nbsp;&nbsp;&nbsp; 打开，用于读取（这是ifstream的缺省模式）<br>out&nbsp;&nbsp;&nbsp; 打开，用于改写（这是ofstream的缺省模式）<br>app&nbsp;&nbsp;&nbsp; 写入是始终添加与尾端<br>ate&nbsp;&nbsp;&nbsp; 打开文件之后令读写位置移至文件尾端<br>trunc&nbsp; 将先前的文件内容移除<br>binary 二进制方式打开<br>这些标致和或在一起。<br>这些标致作为对象构造或open行为的第二个参数，来定义文件打开分方式。<br><br>随机存储<br>用于读文件的随机存储<br>tellg（）&nbsp;&nbsp;&nbsp;&nbsp; 返回读取的位置<br>seekg( pos )&nbsp; 从当前位置移动pos个位子（绝对移送）<br>seekg( offset, rpos )&nbsp; 以rpos位置开始移动offset个位置（相对移动）<br><br>用于写文件的随机存储<br>tellp()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回写入的位置<br>seekp( pos )&nbsp; 从当前位置移动pos个位子（绝对移送）<br>seekp( offset, rpos )&nbsp; 以rpos位置开始移动offset个位置（相对移动）<br><br>读数据<br>利用read行为<br>ifstream ifile<br>ifile.read（buf,length）<br><br>写数据<br>利用write行为<br>ofstream ofile<br>ofile.write（buf,length）
&nbsp;
<br>  <img src ="http://www.cppblog.com/walkspeed/aggbug/23325.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-05-02 13:31 <a href="http://www.cppblog.com/walkspeed/archive/2007/05/02/23325.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Signal中用来管理slot的管理器</title><link>http://www.cppblog.com/walkspeed/archive/2007/04/25/22803.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Wed, 25 Apr 2007 07:18:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/04/25/22803.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/22803.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/04/25/22803.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/22803.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/22803.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>Signal</span><span>会安优先级的不同来调用不同组的</span><span>slot</span><span>。这样要求</span><span>signal</span><span>能根据不同的优先级来管理</span><span>slot</span><span>组。典型的实现方法是用</span><span>std::map</span><span>。将其定义为如下形式</span><span>std::map&lt; int, slot &gt;</span><span>。由于每个优先级下可能有一组</span><span>slot</span><span>，所以要将这一组</span><span>slot</span><span>组织到一起管理，在</span><span>boost signal</span><span>中使用</span><span>std::list</span><span>来管理，其可能的形式大体如下</span><span>std::list&lt; slot &gt;</span><span>。这样就要修改刚才定义的</span><span>map</span><span>了，修改后的</span><span>map</span><span>可能的定义如下</span><span>std::map&lt; int, std::list&lt; slot &gt; &gt;</span><span>。</span>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在实际的</span><span>boost signal</span><span>中并没有直接的存储</span><span>slot</span><span>（</span><span>boost signal</span><span>库中有个</span><span>slot</span><span>类），而是存储了</span><span>function</span><span>（</span><span>boost function</span><span>类的对象）对象。而且为了方便控制</span><span>signal</span><span>与</span><span>function</span><span>之间的联系，引入了</span><span>connection</span><span>类，用来表示</span><span>signal</span><span>与</span><span>function</span><span>之间的联系。</span><span>Connection</span><span>的对象当然和一个</span><span>function</span><span>放在了一起。这样</span><span>boost signal</span><span>提供了一个</span><span>connection_slot_pair</span><span>类来存储一个</span><span>function</span><span>与</span><span>connection</span><span>对。这样在</span><span>boost signal</span><span>中一个</span><span>slot</span><span>组的实际定义如下</span><span>std::list&lt; connection_slot_pair &gt;</span><span>。并且被重定义为</span><span>group_list</span><span>类型（</span><span>typedef std::list&lt;connection_slot_pair&gt; group_list</span><span>）。相应的在</span><span>boost signal</span><span>中</span><span>map</span><span>的实际定义如下</span><span>std::map&lt;stored_group, group_list, compare_type&gt;</span><span>，并且被重定义为</span><span>slot_container_type</span><span>（</span><span>typedef std::map&lt;stored_group, group_list, compare_type&gt; slot_container_type</span><span>）。将以上的这些东西组织到一个类中，以便于管理。这个类就是</span><span>named_slot_map</span><span>。</span><span>Signal</span><span>中真正用来管理</span><span>slot</span><span>的管理器。</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Named_slot_map</span><span>的类数据成员如下定义（</span><span>boost</span><span>源码中的一部分，数据成员部分）</span></p>
<p>&nbsp;</p>
<p align=left><span>class BOOST_SIGNALS_DECL named_slot_map</span></p>
<p align=left><span>{</span></p>
<p align=left><span>public:</span></p>
<p align=left><span>typedef named_slot_map_iterator iterator;//named_slot_map</span><span>容器的迭代器</span></p>
<p align=left><span>private:</span></p>
<p align=left><span>typedef std::list&lt;connection_slot_pair&gt; group_list;//function connection</span><span>对组类型</span></p>
<p align=left><span>typedef std::map&lt;stored_group, group_list, compare_type&gt; slot_container_type;//</span><span>容器类型</span></p>
<p align=left><span>typedef slot_container_type::iterator group_iterator;//</span><span>容器迭代器类型</span></p>
<p align=left><span>typedef slot_container_type::const_iterator const_group_iterator;</span></p>
<p align=left>&nbsp;</p>
<p align=left><span>slot_container_type groups;//</span><span>定义一个用来管理</span><span>function connection</span><span>组的容器对象</span></p>
<p align=left><span>group_iterator back;//</span><span>容器的迭代器对象</span></p>
<p align=left><span>};</span></p>
<p align=left>&nbsp;</p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Named_slot_map</span><span>也是一个容器。</span><span>Stl</span><span>的容器为了外界方便访问容器内数据单元，提供了迭代器。</span><span>Named_slot_map</span><span>也有自己的迭代器。这个迭代器就是</span><span>named_slot_map_iterator</span><span>类。</span><span>Named_slot_map</span><span>提供了以下方法来获得迭代器</span><span>iterator begin()</span><span>，</span><span>iterator end()</span><span>。</span><span>Begin</span><span>方法提供首迭代器，</span><span>end</span><span>方法提供尾迭代器。向容器中插入数据用</span><span>insert</span><span>。清除某个数据用而而然</span><span>erase</span><span>，清空容器中的所有数据用</span><span>clear</span><span>。</span></p>
<img src ="http://www.cppblog.com/walkspeed/aggbug/22803.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-04-25 15:18 <a href="http://www.cppblog.com/walkspeed/archive/2007/04/25/22803.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>由signal的一些东西联想到了AM</title><link>http://www.cppblog.com/walkspeed/archive/2007/04/24/22756.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Tue, 24 Apr 2007 11:36:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/04/24/22756.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/22756.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/04/24/22756.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/22756.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/22756.html</trackback:ping><description><![CDATA[　　敏捷开发中提倡依赖关系倒置，即１依赖接口而非具体类，２使用接口的对象定义接口。<br>　　boost signal中的signal的模板参数是个函数类型。可以将其看成一个接口。signal对象依赖这个接口，而且是有signal定义的。具体类去实现镇魂歌接口（即实现这个函数类型）<br>　　signal和slot框架组成了一个observer模式的实现。signal是出版者，slot是订阅者
<img src ="http://www.cppblog.com/walkspeed/aggbug/22756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-04-24 19:36 <a href="http://www.cppblog.com/walkspeed/archive/2007/04/24/22756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>奇怪于signal中的slot类的用途</title><link>http://www.cppblog.com/walkspeed/archive/2007/04/23/22654.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Mon, 23 Apr 2007 08:57:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/04/23/22654.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/22654.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/04/23/22654.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/22654.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/22654.html</trackback:ping><description><![CDATA[<p>　　本以为slot就是被signal存储并管理的slot。但是通过解读boost的源代码发现这个类并没有被signal直接管理，而仅仅用来构造了下connection。没有发现其他的用途。如果这样，那为何不直接在signal的connect中直接进行connection的构造呢。<br>　　signal的connect函数没有直接接收function对象，而是接收的slot&lt;&gt;对象，而slot&lt;&gt;对象用来接收function。这个function看来未必一定是个函数对象了。可以是个原始函数或类函数了。 这个猜测要证实了才能确定。即便如此，这个类的作用是有限的。不过关于那个tackeable的用法还没有完全高清楚，可能那是这个类存在的理由，也许以后会有什么的发展。但现在确实看不出什么大的用途。<br>　　奇怪于为何在signal中的slot管理器，不去直接管理slot&lt;&gt;的实例，而是管理connection和function的pair。</p>
<p>　　个人觉得在slot&lt;&gt;中的最有用处的函数。<br>void slot_base::create_connection()<br>{<br>&nbsp;basic_connection* con = new basic_connection();</p>
<p>&nbsp;{<br>&nbsp;&nbsp;con-&gt;signal = static_cast&lt;void*&gt;(this);<br>&nbsp;&nbsp;con-&gt;signal_data = 0;<br>&nbsp;&nbsp;con-&gt;blocked_ = false ;<br>&nbsp;&nbsp;con-&gt;signal_disconnect = &amp;bound_object_destructed;<br>&nbsp;}<br>&nbsp;<br>&nbsp;data-&gt;watch_bound_objects.reset(con);</p>
<p>&nbsp;scoped_connection safe_connection(data-&gt;watch_bound_objects);</p>
<p>&nbsp;for(std::vector&lt;const trackable*&gt;::iterator i = data-&gt;bound_objects.begin();<br>&nbsp;&nbsp;i != data-&gt;bound_objects.end(); ++i) <br>&nbsp;{<br>&nbsp;&nbsp;BOOST_SIGNALS_NAMESPACE::detail::bound_object binding;<br>&nbsp;&nbsp;(*i)-&gt;signal_connected(data-&gt;watch_bound_objects, binding);</p>
<p>&nbsp;&nbsp;BOOST_SIGNALS_NAMESPACE::detail::auto_disconnect_bound_object disconnector(binding);</p>
<p>&nbsp;&nbsp;con-&gt;bound_objects.push_back(binding);<br>&nbsp;&nbsp;disconnector.release();<br>&nbsp;}</p>
<p>&nbsp;safe_connection.release();<br>&nbsp;data-&gt;watch_bound_objects.set_controlling(true);<br>}</p>
<img src ="http://www.cppblog.com/walkspeed/aggbug/22654.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-04-23 16:57 <a href="http://www.cppblog.com/walkspeed/archive/2007/04/23/22654.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>得到类数据成员的位置</title><link>http://www.cppblog.com/walkspeed/archive/2007/04/08/21486.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Sun, 08 Apr 2007 02:54:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/04/08/21486.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/21486.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/04/08/21486.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/21486.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/21486.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类的数据成员的布局是按某种顺序的，有一个相对与类的头位子的偏移量，这个偏移量的计算方法如下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (size_t)&amp;(((classname*)0)-&gt;members)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;classname 是一个类名，members是类中任何一个数据成员的名字。0在这里是一个地址，这是一个保留地址，它不能作为左值，但可以作为右值，去提取其中的对象。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在0地址位，构造了一个classname的结构布局。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在使用中去每次写这个表达式还是很麻烦的。可以用个宏将其包起来，如下<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #difine offsetof( ClassName, MemberName ) (size_t)&amp;(((classname*)0)-&gt;members)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实这个宏在windows和linux平台下都以提供了。
<img src ="http://www.cppblog.com/walkspeed/aggbug/21486.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-04-08 10:54 <a href="http://www.cppblog.com/walkspeed/archive/2007/04/08/21486.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>看来的东西集成</title><link>http://www.cppblog.com/walkspeed/archive/2007/04/07/21457.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Sat, 07 Apr 2007 08:28:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/04/07/21457.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/21457.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/04/07/21457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/21457.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/21457.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以下的东西是我在网上看到的东西，摘抄下来的，忘了出处。先向贡献者表示感谢<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thinking in c++ 之static小结<br>本的含义是：&#8220;位置不变的某个东西&#8220;，这里指的是内存中的位置或者文件中的可见性<br>1，在c和c++中，static的两种含义：<br>（1），静态存储。<br>（2），对一个特定的编译单元来说是本地的，这个名字在这个单元或类之外不可见。</p>
<p>2，static对象将存储在程序的静态存储区中，而不是在堆栈中。这个对象只在汉书第一次调用是初始化，其后不用再初始化。</p>
<p>3，对于静态对象的初始化，零赋值只对预定义对象有效，用户自定义的类型必须用构造函数初始化。</p>
<p>4，静态对象的析构函数在程序的main()函数退出时，或者标准c函数exit()调用时才被调用。在析构函数中调用exit()是很危险的，因为这样可能引起死循环。</p>
<p>5，静态对象的销毁是按它们初始化的相反顺序进行的。全局对象总是在main()执行之前被创建。如果一个包含静态对象的函数从没有被调用过，那么这个对象的构造函数就没有被执行，所以也就不会调用析构函数</p>
<p>6，一个被明确声明为static的对象或函数的名字对编译单元来说是局部变量，这些名字有内部连接。类声明和局部变量没有联接。</p>
<p>7，extern表示该名字对所有的编译单元是可见的，用static和extern限定的对象总是驻留在静态数据区</p>
<p>8，普通函数是外部连接的</p>
<p>9，类的静态成员拥有一块单独的存储区,而不管我们创建了多少个该类的对象，这就为这些了创建了一个通信的方法。</p>
<p>10，静态成员的定义必须出现在外部，而且只能有一次</p>
<p>11，一个类的静态常量可以被用作一个编译时常量</p>
<p>12，在局部类(在函数内部定义的类）中不能有静态数据成员。</p>
<p>13，静态成元函数：<br>（1），静态成元函数为该类的全体服务，而不是为类的部分对象服务；<br>（2）,静态成员函数不能访问一般的数据成员，只能访问静态数据成员，并且只能调用静态成元函数。</p>
<p>14，为什么静态成元函数不能访问一般的数据成员，也不能调用普通的成员函数?<br>由于当前对象的地址是被隐藏的传递给被调用的函数的，由于静态成员函数不是某个对象独有的，所以没有this指针，所以无法调用调用普通成员函数，同样对普通成员变量的访问也用到了this指针。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编译单元<br>经过预处理之后的文件（这个是内存中的临时文件）<br>#include在预处理时被展开，宏也一样</p>
<p>一个经过展开后的.cpp文件就是一个编译单元</p>
<p>一个xx.h（经过预处理） + 一个xx.cpp = 一个编译单元<br>一个编译单元（经过编译）= xx.obj<br>整个程序的多个.obj加起来(经过链接) = .exe（可执行文件） </p>
<p><br>预处理<br>-----------<br>把一些带#号的，比方说宏定义，预处理命令（#include）等 <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 内部连接与外部连接<br>在说内部连接与外部连接前，先说明一些概念。 </p>
<p>　　1.声明</p>
<p>　　一个声明将一个名称引入一个作用域;</p>
<p>　　在c++中，在一个作用域中重复一个声明是合法的 </p>
<p><br>　　以下都是声明： </p>
<p>int foo(int,int); //函数前置声明 </p>
<p>typedef int Int; //typedef 声明 </p>
<p>class bar; //类前置声明 </p>
<p>extern int g_var; //外部引用声明 </p>
<p>class bar; //类前置声明 </p>
<p>typedef int Int; //typedef 声明 </p>
<p>extern int g_var; //外部引用声明 </p>
<p>friend test; //友员声明 </p>
<p>using std::cout; //名字空间引用声明</p>
<p>friend test; //友员声明 </p>
<p>using std::cout; //名字空间引用声明</p>
<p>int foo(int,int); //函数前置声明&nbsp; </p>
<p>　　在同一个作用域中你可以多次重复这些声明。 </p>
<p>　　有两种声明不能重复，那就是类成员函数及静态数据成员的声明</p>
<p>class foo <br>{ <br>　static int i; <br>　static int i;//不可以 <br>　public: <br>　　int foo(); <br>　　int foo();//不可以 <br>};</p>
<p>2.定义</p>
<p>　　一个定义提供一个实体(类型、实例、函数)在一个作用域的唯一描述。</p>
<p>　　在同一作用域中不可重复定义一个实体。</p>
<p>　　以下都是定义。</p>
<p>int y;</p>
<p>class foo ;</p>
<p>struct bar ;</p>
<p>foo* p;</p>
<p>static int i;</p>
<p>enum Color;</p>
<p>const double PI = 3.1415;</p>
<p>union Rep;</p>
<p>void test(int p) {};</p>
<p>foo a;</p>
<p>bar b; </p>
<p>　　3.编译单元</p>
<p>　　当一个c或cpp文件在编译时，预处理器首先递归包含头文件，形成一个含有所有必要信息的单个源文件,这个源文件就是一个编译单元。这个编译单元会被编译成为一个与cpp文件名同名的目标文件(.o或是.obj)。连接程序把不同编译单元中产生的符号联系起来，构成一个可执行程序。</p>
<p>　　4.自由函数</p>
<p>　　如果一个函数是自由函数，那么这个函数不是类的成员函数，也不是友元函数。</p>
<p>　　下面来看内部连接和外部连接</p>
<p>　　内部连接：如果一个名称对于它的编译单元来说是局部的，并且在连接时不会与其它编译单元中的同样的名称相冲突，那么这个名称有内部连接(注：有时也将声明看作是无连接的，这里我们统一看成是内部连接的)。</p>
<p>　　以下情况有内部连接:</p>
<p>　　a)所有的声明</p>
<p>　　b)名字空间(包括全局名字空间)中的静态自由函数、静态友元函数、静态变量的定义</p>
<p>　　c)enum定义</p>
<p>　　d)inline函数定义(包括自由函数和非自由函数)</p>
<p>　　e)类的定义</p>
<p>　　f)名字空间中const常量定义</p>
<p>　　g)union的定义</p>
<p>　　外部连接:在一个多文件程序中，如果一个名称在连接时可以和其它编译单元交互，那么这个名称就有外部连接。</p>
<p>　　以下情况有外部连接:</p>
<p>　　a)类非inline函数总有外部连接。包括类成员函数和类静态成员函数</p>
<p>　　b)类静态成员变量总有外部连接。</p>
<p>　　c)名字空间(包括全局名字空间)中非静态自由函数、非静态友元函数及非静态变量</p>
<p>　　下面举例说明：</p>
<p>　　a)声明、enum定义、union定义有内部连接</p>
<p>　　所有的声明、enum定义及union定义在编译后不会产生连接符号，也就是在不同编译单元中有相同名称的声明及enum、union定义并不会在连接时发生发现多个符号的错误。</p>
<p>// main.cpp</p>
<p>typedef int Int; //typedef 声明，内部连接</p>
<p>enum Color; //enum定义,内部连接</p>
<p>union X //union定义，内部连接<br>{<br>　long a;<br>　char b[10];<br>};</p>
<p>int main(void)<br>{<br>Int i = red;<br>return i;<br>}</p>
<p>// a.cpp</p>
<p>typedef int Int; //在a.cpp中重声明一个int类型别名，在连接时不会发生错误<br>enum Color; //在a.cpp中重定义了一个enum Color，在连接时不会发生错误<br>const Int i =blue; //const常量定义，内部连接<br>union X //union定义，内部连接<br>{<br>　long a;<br>　char b[10];<br>}; </p>
<p>　　b)名字空间中静态自由函数、静态友元函数、静态变量、const常量定义有内部连接</p>
<p>// main.cpp</p>
<p>namespace test<br>{<br>　int foo(); //函数声明，内部连接<br>　static int i = 0; //名字空间静态变量定义，内部连接<br>　static int foo() { return 0;} //名字空间静态函数定义，内部连接<br>}</p>
<p>static int i = 0; //全局静态变量定义，内部连接<br>static int foo() {return 1;} //全局静态函数定义，内部连接<br>const int k = 0; //全局const常量定义，内部连接<br>int main(void)<br>{<br>　return 0;<br>}</p>
<p>//a.cpp</p>
<p>namespace test<br>{<br>　int i = 0; //名字空间变量定义，外部连接<br>　int foo() {return 0;} //名字空间函数定义，外部连接<br>}</p>
<p>int i = 0; //全局变量定义，外部连接<br>int k = 0; //全局变量定义，外部连接<br>int foo() { return 2;} //全局函数定义，外部连接 </p>
<p>　　在全局名字空间中，main.cpp中定义了静态变量i,常量k,及静态自由函数foo等，这些都有内部连接。如果你将这些变量或函数的static或是const修饰符去掉，在连接时就会现multiply defined symbols错误，它们与a.cpp中的全局变量、全局函数发生冲突。</p>
<p>c)类定义总有内部连接,而非inline类成员函数定义总有外部连接，不论这个成员函数是静态、虚拟还是一般成员函数，类静态数据成员定义总有外部连接。 </p>
<p>　　1.类的定义有内部连接。如果不是，想象一下你在4个cpp文件中include定义了类Base的头文件，在4个编译单元中的类Base都有外部连接，在连接的时候就会出错。</p>
<p>　　看下面的例子:</p>
<p>//main.cpp</p>
<p>class B //类定义，内部连接<br>{<br>　static int s_i; //静态类成员声明，内部连接 <br>　public:<br>　　void foo() { ++s_i;} //类inline函数，内部连接<br>};<br>struct D <br>{<br>　void foo(); //类成员函数声明，内部连接<br>};</p>
<p>int B::s_i = 0; //类静态数据成员定义，外部连接<br>void D::foo() //类成员函数定义，外部连接<br>{ <br>　cout &lt;&lt; "D::foo in main.cpp" &lt;<br>}</p>
<p>int main() //main函数，全局自由函数，外部连接<br>{<br>　B b;<br>　D d;<br>　return 0;<br>}</p>
<p>//a.cpp</p>
<p>class B<br>{<br>　int k;<br>};</p>
<p>struct D<br>{<br>　int d;<br>};&nbsp; </p>
<p>　　在这个例子中，main.cpp与a.cpp中都有class B和class D的定义，但在编译这两个cpp文件时并不发生link错误。</p>
<p>　　2.类的非inline成员函数(一般，静态，虚拟都是)总有外部连接，这样当你include了某个类的头文件，使用这个类的函数时，就能连接到正确的类成员函数上，继续以上面为例子，如果把a.cpp中的struct D改为</p>
<p>struct D //类定义<br>{<br>　int d;<br>　void foo(); //类成员函数声明<br>};<br>void D::foo() //类成员函数定义，外部连接<br>{<br>　cout &lt;&lt; " D::foo in a.cpp" &lt;<br>}&nbsp; </p>
<p>　　这时main.cpp与a.cpp中的D::foo都有外部连接，在连接就会出现multiply defined symbols错。 </p>
<p>　　3.类的静态数据成员有外部连接，如上例的B::s_i,这样当你在main.cpp中定义了类静态数据成员，其它编译单元若使用了B::s_i,就会连接到main.cpp对应编译单元的s_i。</p>
<p>　　d)inline函数总有内部连接，不论这个函数是什么函数</p>
<p>// main.cpp</p>
<p>inline int foo() { return 1;} //inline全局函数，内部连接<br>class Bar //类定义，内部连接<br>{<br>　public:<br>　　static int f() { return 2;} //inline 类静态函数，内部连接<br>　　int g(int i) { return i;} //inline 类成员函数，内部连接<br>};</p>
<p>class Base<br>{<br>　public:<br>　　inline int k()； //类成员函数声明，内部连接<br>}；</p>
<p>inline int Base::k(){return 5;} //inline 类成员函数，内部连接<br>int main(void)<br>{<br>　return 0;<br>} </p>
<p>　　如果你的Base类是定义在Base.h中，而Base的inline 函数是在Base.cpp中定义的，那么在main.cpp中include "Base.h"编译不会出现问题，但在连接时会找不到函数k，所以类的inline函数最好放到头文件中，让每一个包含头文件的cpp都能找到 inline函数。</p>
<p>　　现在对c++中的连接有了一个认识，能清楚的知道是什么原因产生连接时错误。当你在连接时产生连接不到的错误，这说明所有的编译单元都没有这个实体的外部连接；当你在连接时发现有多个连接实体，这说明有多个编译单元提供了同名的有外部连接的实体。同时，在进行程序设计时，也要注意不要使只有本编译单元用到的函数、类、变量等有外部连接，减少与其它编译单元的连接冲突。</p>
<p>　　不过在这里没有说明template函数及template class的连接性，并且对一些特别的情况也没有作出说明(比如inline函数不能被inline)。<br></p>
<img src ="http://www.cppblog.com/walkspeed/aggbug/21457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-04-07 16:28 <a href="http://www.cppblog.com/walkspeed/archive/2007/04/07/21457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译单元的理解</title><link>http://www.cppblog.com/walkspeed/archive/2007/04/07/21456.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Sat, 07 Apr 2007 08:24:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/04/07/21456.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/21456.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/04/07/21456.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/21456.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/21456.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编译单元，是代码的物理组织形式。有时在单个的&#8216;.h&#8217;或&#8216;.cpp&#8217;的编写中看没有问题的代码，在编译单元中就是有问题的。特别是软件规模大时。<br><br>编译器不会去编译'.h'或者'.hpp'文件。<br>编译器只会编译'.c'或'.cpp'文件。</p>
<p>'.h'或'.hpp'里的代码会被#include宏添加到'.c'或'.cpp'文件中。<br>这个过程发生在预编译期，预编译器（现在好像没有这个东西了，都<br>在编译器中完成）完成这份工作。</p>
<p>一个'.c'或'.cpp'是一个编译单元。编译器将其翻译成二进制代码。</p>
<img src ="http://www.cppblog.com/walkspeed/aggbug/21456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-04-07 16:24 <a href="http://www.cppblog.com/walkspeed/archive/2007/04/07/21456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Metafunction 原操作</title><link>http://www.cppblog.com/walkspeed/archive/2007/04/07/21454.html</link><dc:creator>walkspeed</dc:creator><author>walkspeed</author><pubDate>Sat, 07 Apr 2007 08:20:00 GMT</pubDate><guid>http://www.cppblog.com/walkspeed/archive/2007/04/07/21454.html</guid><wfw:comment>http://www.cppblog.com/walkspeed/comments/21454.html</wfw:comment><comments>http://www.cppblog.com/walkspeed/archive/2007/04/07/21454.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/walkspeed/comments/commentRss/21454.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/walkspeed/services/trackbacks/21454.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这是我在看boost MPL时试着翻译的东西，现在贴上来。<br><br>A metafunction is a class or a class template that represents a function invocable at compile-time. <br>一个原操作是在编译器表现了调用操作的一个类或一个模板类。</p>
<p>An non-nullary metafunction is invoked by instantiating the class template with particular template parameters (metafunction arguments); <br>一个非无参的原操作被一个有详细模板参数的模板类请求；<br>the result of the metafunction application is accessible through the instantiation's nested type typedef. <br>原操作应用的返回值是一个通过模板类实例可取的内嵌的类型定义。</p>
<p>All metafunction's arguments must be types (i.e. only type template parameters are allowed). <br>所有的原操作的参数必须是类型。</p>
<p>A metafunction can have a variable number of parameters. <br>一个原操作能有一个数量变化的参数</p>
<p>A nullary metafunction is represented as a (template) class with a nested type typename member.<br>一个无参数原操作被表现为有内嵌重命名类型的类</p>
<p>原操作的三种表达式（f是一个原操作）<br>1 f::type<br>2 f&lt;&gt;::type<br>3 f&lt; a1,..,an &gt;::type</p>
<p><br>Lambda Expression 构造和分配表达式</p>
<p>A Lambda Expression is a compile-time invocable entity in either of the following two forms:<br>一个构造和分配表达式是下面两个中的一个编译期调用单元</p>
<p>Metafunction Class<br>原操作类</p>
<p>Placeholder Expression <br>站位符表达式</p>
<p>Most of the MPL components accept either of those, and the concept gives us a consice way to describe these requirements.<br>大部分的MPL组件接收它们其中一个，</p>
<img src ="http://www.cppblog.com/walkspeed/aggbug/21454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/walkspeed/" target="_blank">walkspeed</a> 2007-04-07 16:20 <a href="http://www.cppblog.com/walkspeed/archive/2007/04/07/21454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>