??xml version="1.0" encoding="utf-8" standalone="yes"?>久久国产免费,久久精品人人槡人妻人人玩AV,久久精品国产2020http://www.shnenglu.com/yuanyajie/category/3707.html记录所思所惻I收藏所见所闻�? zh-cnThu, 07 May 2009 16:44:02 GMTThu, 07 May 2009 16:44:02 GMT60试用新版本luabindhttp://www.shnenglu.com/yuanyajie/archive/2009/05/07/82117.html清源游民清源游民Wed, 06 May 2009 16:46:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2009/05/07/82117.htmlhttp://www.shnenglu.com/yuanyajie/comments/82117.htmlhttp://www.shnenglu.com/yuanyajie/archive/2009/05/07/82117.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/82117.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/82117.html先把lua, luabind ~成静态库Q(下图只是debug,releasecM)Q?br>

做完之后整理Qlua, luabind 以sdk 形式l织好,我是q样l织:
\luabind_build\sdk\luabind\include
\luabind_build\sdk\luabind\msvc-9.0-sp1\lib
\luabind_build\sdk\lua\include
\luabind_build\sdk\lua\msvc-9.0-sp1\lib
q样Q把sdk中的东东保存一份,方便以后使用。写一个MFC程序测?br>

 1 //关键代码
 2 //mfc class function
 3 void CMFC_LuaDlg::SetEditText(const char* text)
 4 {
 5     Edit_1.SetWindowText(text);
 6     UpdateData(FALSE);
 7 }
 8 //register
 9 luabind::module(L)
10     [
11     luabind::class_<CMFC_LuaDlg>("mfc_dlg")
12       .def"set_text",&CMFC_LuaDlg::SetEditText)
13     ];
14 //load lua file
15 if (0==luaL_dofile(L,filepath))
16     {
17         ret=true;
18     }
19 //run lua function
20  luabind::call_function<void>(L,"update_text",dlg);
21 
脚本内容:
1 function update_text(dlg)
2    dlg:set_text("你好Q欢q来到lua 脚本世界")
3 end
q行l果Q?br>



清源游民 2009-05-07 00:46 发表评论
]]>
c++,要细心不能想当然http://www.shnenglu.com/yuanyajie/archive/2009/05/06/82091.html清源游民清源游民Wed, 06 May 2009 13:09:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2009/05/06/82091.htmlhttp://www.shnenglu.com/yuanyajie/comments/82091.htmlhttp://www.shnenglu.com/yuanyajie/archive/2009/05/06/82091.html#Feedback1http://www.shnenglu.com/yuanyajie/comments/commentRss/82091.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/82091.html
1 class Data;
2 Data* FindData();
3 void GetData(Data* dataPtr)
4 {
5     dataPtr=FindData();
6 }
7 Data* data=NULL;
8 GetData(data);
9 data->somefunction();
W二D代码,更得仔细?br>
 1 class A;
 2 class B;
 3 const * GetA();
 4 const * GetB();
 5 template<typename T>
 6 int GetSpecialValue(T* classPtr)
 7 {
 8    return  3721;
 9 }
10 
11 template<>
12 int GetSpecialValue<>(A* classPtr)
13 {
14    return  37;
15 }
16 template<>
17 int GetSpecialValue<>(B* classPtr)
18 {
19    return 21;
20 }
21 const * classPtr=GetA();
22 int ret=GetSpecialValue(classPtr);
23 cout<<ret<<endl; //out 3721! why not 37?
24 
25 
26 
W一D늚问题在于看到指针惛_然认为是地址Qdata 可以带回反回|其实因ؓq里是g递,实参data把自qDl了dataPtr,dataPtr后来实从FindData()得到了想要的|但这对一点媄响也没有Q所以函数返回时Qdata的值没有发生变化,也就是没有带回想要的倹{?br>只要不想当然Q仔l一惛_明白了,解决办法很简单:
1  void GetData(Data*& dataPtr)
2 4 {
3 5     dataPtr=FindData();
4 6 }
W二D늚问题是没有注意到那个const, T*  ?T const* 是不一LQ不能完全匹配,所以不会找到对Acd的特化版?解决办法可以q样Q?br>
 1 template<typename T>
 2 int GetSpecialValue(T const* classPtr)
 3 {
 4    return  3721;
 5 }
 6 
 7 template<>
 8 int GetSpecialValue<>(A const* classPtr)
 9 {
10    return  37;
11 }
12 template<>
13 int GetSpecialValue<>(B const* classPtr)
14 {
15    return 21;
16 }
能过q两个小例子可以知道,C++l节很多Q要仔细Q不能想当然?br>

清源游民 2009-05-06 21:09 发表评论
]]>
Q网摘好文)C++多态技术的实现和反?/title><link>http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36260.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Fri, 09 Nov 2007 14:32:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36260.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/36260.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36260.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/36260.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/36260.html</trackback:ping><description><![CDATA[     摘要:   <a href='http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36260.html'>阅读全文</a><img src ="http://www.shnenglu.com/yuanyajie/aggbug/36260.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2007-11-09 22:32 <a href="http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36260.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Q网摘好文)关于野指?/title><link>http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36259.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Fri, 09 Nov 2007 14:21:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36259.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/36259.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36259.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/36259.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/36259.html</trackback:ping><description><![CDATA[     摘要:   <a href='http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36259.html'>阅读全文</a><img src ="http://www.shnenglu.com/yuanyajie/aggbug/36259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2007-11-09 22:21 <a href="http://www.shnenglu.com/yuanyajie/archive/2007/11/09/36259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>|摘Q一介lDirectX 10 的文?/title><link>http://www.shnenglu.com/yuanyajie/archive/2007/05/31/25201.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Thu, 31 May 2007 07:11:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2007/05/31/25201.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/25201.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2007/05/31/25201.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/25201.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/25201.html</trackback:ping><description><![CDATA[Microsoft发布的DirectX 10代表了自从可~程Shader出现以来?D API斚w的最巨大的进步。通过一番脱胎换骨般的重建,DirectX 10展现Zpd非常醒目的新Ҏ,包括高度优化的运行时Q强大的Geometry ShaderQ纹理数l等{,q些Ҏ将引领PC实时三维囑Şq入一个全新的世界? <h2>DirectX 发展?/h2> <p>  在过ȝ十年中,<a ><u><font color=#0000ff>DirectX</font></u></a>已经Ex成ؓ了Microsoft Windowsq_上进行游戏开发的首选API。每一代的DirectX都带来对新的囑ŞgҎ的支持Q因此每ơ都能帮助游戏开发者们q出惊h的一步?/p> <p>  微YDirectX API(Application Programming interface :应用E序界面) 最早发布于1995q_其设计目标是为Windowsq_软g开发h员提供一个更便的针对多媒体和游戏应用~程的标准接口?/p> <p>  在DirectX出台Q开发者针寚w频、视频等的操作必d于硬件进行,——当ӞZOpenGL能够在很大程序上减轻工作量,但OpenGL获得的支持显然远q不够。——而显卡、声卡等的品种cM多,要编写一ƾ能q行在所有^C的游戏简直是一件噩梦般的工作?/p> <p>  通过提供一pd的针对多媒体应用的APIQ如囑Ş(包括2D?D应用)、音频或输入讑֤{,DirectX提供了一整套的多媒体接口ҎQ这可以让开发者根据API~写相应的Y件程序,而不必考虑具体的硬Ӟg的差别性显得无重,~程人员得以更有效率的开发各U多媒体、游戏Y件?/p> <p>  当然QDirectX的发展ƈ不是一帆风的Q最初的版本q谈不上E_。 </p> <p> <table class=atable cellSpacing=1 cellPadding=1 width=440 align=center> <tbody> <tr class=tbhead> <td>版本</td> <td>操作pȝ</td> <td>发布日期</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 1.0</td> <td>Windows 95a</td> <td>9/30/95</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 2.0/2.0a</td> <td>Windows 95OSR2/NT4.0</td> <td>6/5/96</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 3.0/3.0a</td> <td>Windows NT 4.0 SP3</td> <td>9/15/96</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 4.0</td> <td></td> <td>未发?/td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 5.0</td> <td>Windows NT 4.0/Beta for NT 5.0</td> <td>7/16/97</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 5.1</td> <td>Windows 95/98/NT4.0</td> <td>12/1/97</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 5.2</td> <td>Windows 95</td> <td>5/5/98</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 6.0</td> <td>Windows 98/NT4.0</td> <td>8/7/98</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 6.1</td> <td>Windows 95/98/98SE</td> <td>2/3/99</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 7.0</td> <td>Windows 95/98/98SE/2000</td> <td>9/22/99</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 7.0a</td> <td>Windows 95/98/98SE/2000</td> <td>9/99</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 7.1</td> <td>Windows 95/98/98SE/ME/2000</td> <td>9/16/99</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 8.0/8.0a</td> <td>Windows 95/98/98SE/ME/2000</td> <td>9/30/2000</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 8.1</td> <td>Windows 95/98/98SE/ME/2000/XP</td> <td>11/12/01</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 9 <br>Shader Model 2.0</td> <td>Windows 95/98/98SE/ME/2000/XP</td> <td>12/19/2002</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 9 <br>Shader Model 2.0b</td> <td>Windows 98/98SE/ME/2000/XP</td> <td>8/13/2003</td> </tr> <tr class=tbnmal> <td class=lbt>DirectX 9<br>Shader Model 3.0</td> <td>Windows 98/98SE/ME/2000/XP</td> <td>8/9/2004</td> </tr> </tbody> </table> </p> <h2>DirectX 3D的发?/h2> <p>  DirectX中应用在3D囑Ş斚w的特定DirectX API即Direct3DQ这也是DirectX中最重要的部分。不q,DirectX 3D得到q泛应用是在DirectX 6.0之后Q?/p> <p>  <strong>DirectX 6.0</strong>Q加入了双线性过滤、三U性过滤等优化3D囑փ质量的技术,加入环境影射凹凸贴图Q3D游戏的画面更h真实感?/p> <p>  <strong>DirectX 7.0</strong>Q最大的特色是支持了T&LQ中文名U是“坐标转换和光?#8221;Q?D游戏中坐标和灯光的{换工作从此由CPU转交l了GPUQ比DX6.1性能提升20%。这也成׃nVIDIA GeForce 256与ATi Radeon 256的辉煌,?DFXd退出市场竞争?/p> <p>  <strong>DirectX 7.0a</strong>Q增Z力反馈游戏控制设备的性能和兼Ҏ?/p> <p>  <strong>DirectX 7.1</strong>Q与Windows Millennium一同发布?/p> <p>  <strong>DirectX 8.0/8.0a</strong>Q支持Shader Model 1.0?.1Q从此在昑֍中引入可~程像素着色器(Pixel Shaders)和顶点着色器(Vertex Shaders)的概念,同时应用在Xbox游戏Z。同gT&L仅仅实现的固定光p{换相比,VS和PS单元的灵zL更大,它GPU真正成ؓ了可~程的处理器?/p> <p>  <strong>DirectX 8.1</strong>Q?Pixel Shader升?.2?.3?.4版,可以支持最高每旉28指o执行Q其?.4版当时仅ATi Radeon 8500昑֍支持?/p> <p>  <strong>DirectX 9.0 Shader Model 2.0</strong>Q?SM2.0的shader性能更强Q支持最?6指o的pixel shader长度Q同时DirectPlay和一些音频方面也有大q提升?/p> <p>  <strong>DirectX 9.0 Pixel Shader 2.0b</strong>Q?ATI Radeon X600/700/800pd昑֍首先采纳Q开始支持更多指?最?536)和更多时寄存器(32相比之前?2)Q同时还加入新的贴面寄存?facing register)和几何实?geometry instancing)的支持?/p> <p>  <strong>DirectX 9.0 Shader Model 3.0</strong>Q支持更多指令,支持指o的流量控制和动态分支,从而得编Eh员可以在shaders中加入@环操作,使得~程更加ҎQ首ơ被Geforce 6800昑֍采用?/p> <p>  从DirectX的发展史中我们可以看刎ͼ微Y?D API和硬件一同发展,新硬件带来新的DXҎ,新的DXҎ加速硬件的发展Q在DirectX10上面Q又是一?D囑Ş发展的新境界?/p> <h2>DirectX 10的架构优?/h2> <p>  DirectX之所以在q大的开发者中行Q是得益于它的简单易用和丰富的功能特性。然而,DirectX一直被一个主要的问题所困扰Q那是高CPU负蝲?/p> <p>  在图形编EAPI出现之前Q?D应用E序直接向图形硬件发送命令来完成囑Ş的绘制工作。虽然这样开发工作比较繁重,但硬件效率则能在很大E度上得C证?/p> <p>  而如DirectX和OpenGLq样的图形API则是通过在图形硬件和应用E序之间架v了一个中间层Q这P应用E序可以使用l一的图形编E代码来完成对底层硬件的操作Q将E序员们从与大量的图形硬件交互的恶梦中解救出来。但是,q也造成了每ơDirectX从应用程序那里接收到一条命令时Q就必须先对q条命oq行分析和处理,再向囑Şg发送相对应的硬件命令。由于这个分析和处理的过E由CPU完成Q造成了每一?Dl图命o都会带来CPU的负载?/p> <p>  从技术角度,q种CPU负蝲l?D图象带来两个负面影响Q首先,限制了画面中可以同时l制的物体数量;其次Q限制了可以在一个场景中使用的独立的Ҏ的数量。这׃得游戏画面中的细节数量受C很大的限Ӟ而图像具有真实感的主要要求便是丰富的l节?/p> <p>  DirectX 10的主要优势便是最大程度地降低了CPU负蝲Q主要通过三个途径来达到这个目的:W一Q修改API核心Q得绘制物体和切换材质Ҏ时的消耗降低,提高l图效率Q第二,引入新的机制Q降低图形运操作对CPU的依赖性,使更多的q算在GPU中完成;W三Q大量的物体可以通过调用单条DirectXl制命oq行扚wl制?/p> <p>  下面我们来仔细的看一下这三种方式Q?/p> <p>  <strong>提高l图效率</strong></p> <p>  在DirectX 10中,对上代DirectX版本中三l数据和l制命o的验证过E进行了很大E度的修攏V所谓三l数据和命o的验证,是指在DirectXl制囑Ş之前Q对传给它的囑Ş数据和绘制命令进行格式和数据完整性的查,以保证它们被送到囑Şg时不会导致硬件出问题Q这是很必要的一步操作,但是不幸的是q会带来很大的性能开销?/p> <p><img class=artimg alt="DirectX 9 vs. DirectX 10" src="http://www.highdiy.com/upimg/uploadimg/20061112/055430192.gif"></p> <p>  从上表我们可以很Ҏ的看出,在DirectX 9中,每次l制一帧画面之前,都会对即用的相关数据q行一ơ验证。而DirectX 10中,仅当q些数据被创建后验证一ơ。这很明显是可以大大提高游戏q行中的效率的?/p> <strong>降低囑Şq算对CPU的依?/strong> <p>  在降低图形运对CPU的依赖方面,DirectX 10 引入的三个重要机制就是:U理阵列(texture arrays)、绘刉?(predicated draw)和流式输?stream out)。不要被q三个晦涩的名词吓倒,实际上它们是三个不难理解的机制?/p> <p>  <em>U理阵列</em></p> <p>  传统的DirectX在多张纹理中q行切换的操作是U很lCPU带来很大压力的操作,因ؓ每切换一ơ,都要调用一ơDirectX的API函数。而每l制一个用新U理的物体,pq行一ơ这L切换操作Q有时ؓ了实现特D的材质ҎQ绘制一个物体时可能p切换好几ơ纹理,开销很大?/p> <p>  所以,之前游戏中经怼出现大量的纹理拼合到一张大的纹理中Q通过l不同的三维物体分配q张大纹理的不同局部的方式Q以期减纹理切换,提高游戏q行效率。这U方式实现v来相当复杂,而且DirectX 9中对U理的尺寸的限制?048×4048像素Q也是_如果要容下更多的纹理块Q可能就得加载很多张q样的大U理?/p> <p>  DirectX 10引入的新的纹理阵列机构,允许在一个由昑֍l护的阵列中容纳512张单独的U理Q而且Q在shaderE序中可以用一条新的指令来获取q个阵列中的L一张纹理。而这Ushader指o是运行在GPU中的Q这P把原来要消耗很多CPU旉的纹理切换工作轻村֜转给了GPU。由于纹理一般是直接攑֜昑֭中的Q因此以q样的方式,工作交与和昑֭一同位于显卡上的GPU来完成更有效率。如今,在DirectX 10中,只要一开始设|好U理阵列中的U理Q然后每ơ绘制一个物体时为它指定一个纹理的索引Pq同物体三维数据一起传递到shader中,可以放心的让GPU来给物体选纹理了?/p> <p>  <em>l制预测</em></p> <p>  在一般的三维场景里,很多物体都是完全被别的物体挡在后面的。这时候如果要昑֍l制q些物体是白费力气。尽高U的GPU可以通过g法场景画面中被挡住的像素(注意是像?预先剔除Q但是仍然会有很多不应进行的多余q算。例如,一个完全被挡住的复杂的角色模型Q它的n上可能有几千个顶点,需要做复杂的骨骼皮肤动d理、顶点光照运等{,然而,GPU是在处理完这些顶点之后,q要把这个角色模型一个像素一个像素地d画面中时Q才开始判断每个像素是否需要画Q而当所有的像素都被剔除了时Q之前做的顶点处理也全白费了。在DirectX 10中的l制预测便正是针对这U情늚解决Q简a之,l制预测通过用一个可以代表某个复杂物体的单物体来判断q个物体是否被全部挡住了Q例如用一个可以罩住刚才那个角色的大盒子,当绘制这个盒子时Q如果发现所有的像素都被屏蔽掉了Q也x说这个盒子肯定完全看不见Q那么,里面的角色绘制包括骨骼皮肤运等之类的操作便完成不必q行。而一个盒子顶多有八个点Q相比处理几千个点Q开销得多?/p> <p>  另外Q以前这个步骤中有些真运也需CPU完成的,在DirectX 10中,已经完全交由GPU来做Q这也可以在一定程度上减轻CPU的压力?br><em>数据式输出</em></p> <p>  数据式输出也是DirectX 10的重要特性,它允许GPU上的Vertex shader或Geometry shader向显存中d数据Q而这在以往的vertex shader中是不可能的?/p> <p>  在之前的DirectX版本中,vertex shader只能d昑֭中已有的点数据Q而DirectX 10中引入的新的Geometry shaderQ不但能d昑֭中的点数据、几?炏V线Dc三角Ş)数据Q还可以生成新的几何数据攑֛昑֭?/p> <strong>扚wl制</strong> <p>  在DirectX 9中,Ҏ染状态的理一直是个十分信赖于CPUq算能力的操作。所谓渲染状态,是指昑֍q行一ơ绘制操作时所需要设|的各种数据和参数。例如,要绘制一个h物角Ԍ需要先讄他的几何模型数据的数据格式、纹理过滤模式、半透明混合模式{等Q每讄一,都要调用一ơDirectX APIQ占用大量CPU旉Q极大的U束了渲染的性能?/p> <p>  Z使这些操作能够批量的q行QDirectX 10中引入了两个新的l构——状态对?state object)和常量缓?constant buffers)?/p> <p>  状态对象就是将以前的零散状态按照功能归lؓ几个整体Q这P当要讄一pd相关状态时Q无需为每一个状态来调用一ơDirectX API,只需要调用一ơ将q些状态统l设|到昑֍中去?/p> <p>  而常量缓冲是另一个十分有意义的机制。在l制模型前的准备工作中,渲染状态的讄只是一部分。还是拿l制人物角色来说Q能照亮q个人的光源的颜艌Ӏ位|、类型、范围等{,都要提前讄昑֍Qؓ了通过骨骼来带动他的皮肤做出姿势,q要讄骨骼的位|信息等{,而这些东西主要都是通过GPU中的帔R寄存?constant registers)来传递给它的。每个常量寄存器可以存储一?l的点型向?卛_个QҎ)。常量寄存器是游戏程序向GPU输入游戏场景中数据的重要途径?/p> <p>  在DirectX 9中,q种帔R寄存器的数量是十分有限的Q而且每次更新一个寄存器Q都需要调用一ơDirectX API函数。DirectX 10通过使用帔R~冲(constant buffer)q种l构Q在每个constant buffer中都可以容纳4096个常量,而且只需调用一ơAPI可以更C大批帔R?/p> <p>  比如_在以前的DirectX版本中,如果E序惛_场景里画很多的树木和杂草Q可以采用一个类g“克隆”的方法:先做好一|几棵树、草的三l模型,然后在画一帧画面时Q不停的在不同的位置、方向,用不同的大小为参敎ͼ调用DirectX API的绘制函数来画这些模型,可以画出很多草木来。但是每M,都要讄一大堆参数后调用一ơAPIQ这是很耗CPU旉的,所以在以前的游戏中鲜有大规模且l节丰富的森林场景?/p> <p>  而在DirectX 10中,我们可以先把树、草的几个模型设l显卡,然后所有要ȝ树木的位|、方向和大小一ơ性的写入到constant buffer中,q样Q显卡便一下把所有的树木和草都一L制出来了?/p> <p>  MQDirectX 10通过提前数据验证、纹理阵列、绘刉、流式输出、状态对象、常量缓冲等机制Q帮助游戏的效果和效率上升到一个新的高度。这P也避免了之前DirectX版本因CPU负蝲q大而无法对囑Ş实施更多l节优化的问题?/p> <h2>Shader Model 4.0</h2> <p>  DirectX 10另一个引人瞩目的Ҏ便是引入了Shader Model 4.0Q那么,Shader Model 4.0能够带来怎样的新Ҏ,特别是将它与DirectX 9.0c中Shader Model 3.0相比Ӟ</p> <p>  <em>引入新Shader : Geometry shader</em></p> <p>  DirectX 10新引入的Geometry ShaderQ可以简单地~程操纵几何囑օQ同Ӟ vertex、geometry、pixel shader采用了统一的Sahder架构?/p> <p>  Geometry shaders是可~程囑Ş水U的一大进步。它W一ơ允许由GPU来动态的生成和销毁几何图元数据。通过和新的数据流输出功能配合使用Q许多以前无法实施的法现在都可以在GPU中用了?/p> <p>  <em>l一的Shader架构</em></p> <p>  在DirectX 9中,Pixel shaderL在各个方面落后于vertex shadersQ包括常量寄存器个数、可用的指o个数、shader长度{。程序员需要区分对待这两种shader?/p> <p>  而在shader model 4中,无论 vertex、geometry和pixel shaderQ均有统一的指令集、同L临时/帔R寄存器个敎ͼ它们^{的׃nGPU中的所有可用资源。这P在编E时便不必再考虑每种shader自n的限制了?/p> <p>  <em>癑ր于DirectX 9的可用资?/em></p> <p>  对于shader中可用的资源Q在Shader model 4.0中比原来有了惊h的扩充。就像早期的E序员们l尽脑汁的省着用可怜的640k内存一P在用以前的DirectX开发游戏的q程中,E序员需要小心翼的分配珍贵的shader寄存器资源。寄存器的数量,直接影响着shaderE序的复杂度。这和在640k内存?机器上,怎么也不可能写出Microsoft Officeq样的大规模软g是同一个道理?/p> <p>  而在DirectX 10中,时寄存器由原来的32个扩充到?096个,常量寄存器由原来的256个扩充到?5536个?/p> <p>  <em>更多的渲染目?Render Target)</em></p> <p>  所谓渲染目标,是指GPU可以把画面绘制到的目标,我们可以把它理解为GPU的画布。一般来_渲染目标被输出到屏幕上,q样我们p看到d的画面了。但是有时ؓ了实C些特效,某些渲染l果q不直接d屏幕上,而是再返lGPU做进一步的Ҏ处理Q而且渲染目标中也不一定是d的画面的颜色信息?/p> <p>  Ҏ囑ŞҎ的需要,渲染目标可能是每个物体距dq的q近Q或者物体表面上每个像素的方向,或者每个物体表面的温度{等Q之Z实现ҎQ可以按需要在其中l制M信息。ؓ了提高这U情况下的效率,很多新的昑֍都支持在同一遍Shader执行l束后,同时把不同的信息l制C同的渲染目标中。在DirectX 9中就已经支持q种机制了,但是它约束最多同时向四个渲染目标l制。而DirectX 10这个数量提升了一倍?/p> <em>更多的纹?/em> <p>  在Shader Model 4.0中提供了对纹理阵?Texture arrays)的支持。在前文中已l对U理阵列有了比较详细的介l,在这里只着重介l一下与shader相关的部分?/p> <p>  在每个纹理阵列中Q最多可以保?512张同样大的U理。而且每张贴图的分辨率被扩展到?192×8192。更大的分L率意味着U理中更丰富的细节。在一个shader中能够同时访问的U理个数被增加到?28个,也就是说在每ơ执行同一个shaderӞ可以使用一个纹理阵列的512个纹理中?28个。所以说Q在DirectX 10中,U理的多h和l节E度会有大q的提升?/p> <p>  <em>新的HDR颜色格式</em></p> <p>  要说q些q来在实时图形界炒得最热的概念Q应该是<a >HDR</a>了。它通过采用点格式的颜色格式来为纹理、光照等计算提供极大的精度和颜色范围(以前的纹理一?都是采用整数型的颜色格式)。尽最后显C到屏幕上还是每个颜色通道8位的整数格式Q但是以前由于在材质、光照计中U理也是用每通道8位的格式来参与计,所以在昄到画面之前,很多l节在低精度的q算中丢׃?/p> <p>  而采用每颜色通道16位QҎ的纹理,能够保证在运过E中几乎没有颜色l节信息的丢失。另外,采用16位QҎ式的颜色通道Q可以表现更大的颜色范围。这些就是HDR的优性?/p> <p>  对用戯言Q当游戏中的画面|上一层HDR效果后,立刻昑־和真正的照片一P有朦胧的光晕、细致的高光和十分自然的色调?/p> <p>  然而,采用每个颜色通道16位QҎ的格式,比采用每通道8位的整数格式的纹理要多占据一倍的昑֭Q这l绘制的效率带来了负面的影响。所以在 DirectX 10中引入了两个新的HDR格式。第一U是R11G11B10Q表C红色和l色通道?1位QҎQ而蓝色通道采用10位QҎ表示。那么,Z么不都用 11位呢Q这是ؓ了凑32q个整数。学q计机的h都知道,当内存中一个数据单元的宽度?2位时Q对它的操作效率最高;而且在纹理数据中一般要求每个像素的数据宽度?的倍数Q如2,8,16,32,64{等。又因ؓ人眼对蓝色的敏感度不如对U色和绿Ԍ所以它比其他两个通道用了一位?/p> <p>  另外一U格式是采用每通道9位尾数、所有通道׃n5位指数的形式(众所周知Q在计算ZQQҎ是采用尾数附加指数的形式来表C的)Q加hq是32位?q些新的格式使得U理能够与原来占用同样多的显存空_避免了大的空间和带宽消耗。同ӞZ适合需要精的U学计算的场合,DirectX 10能够支持每通道32?4个通道加v?28?_ֺ的QҎU理?/p> <p>  DirectX 10中带来的q些扩充和提高,使得创徏前所未有的细节的实时游戏场景真正成ؓ可能?/p> <h2>几何着色器与流式输?/h2> <p>  在DirectX 10发布之前Q图形硬件只有在GPU上操作已有数据的能力。顶点着色器(Vertex Shader)和像素着色器(Pixel Shader)都允许程序操作内存中已有的数据。这U开发模型非常成功,因ؓ它在复杂|格蒙皮和对已有像素q行_计算斚w都表现的很出艌Ӏ但是,q种开发模型不允许在图像处理器上生成新数据。当一些物体在游戏中被动态的创徏?比如新型武器的外?Q就需要调用CPU。可惜现在大多数游戏已经很给CPU带来了很大的压力Q游戏进行时动态创建庞大数量新数据的机会就变得微乎其微了?/p> <p>  Shader Model 4.0中引入的几何着色器(Geometry Shader)Q第一ơ允许程序在囑փ处理器中创徏新数据。这一革命性的事g使得GPU在系l中的角色由只可处理已有数据的处理器变成了可以以极快速度既可处理又可生成数据的处理器。在以前囑Şpȝ上无法实现的复杂法现如今变成了现实?/p> <p>  几何着色器被放在顶点着色器和光栅化阶段(Rasterizer)中间。所谓光栅化Q就是一行一行的扫描每个三角形,把它们一个像素一个像素的l制到画?上。几何着色器把经q顶点着色器处理q的点当作输入Q对于每个顶点,几何着色器可以生成1024个顶点作出。这U生成大量数据的能力叫做数据扩大 (Data Amplification)。同LQ几何着色器也可以通过输出更少的顶Ҏ删除点Q因此,叫做数据羃?Data Minimization)。这两个新特性GPU在改变数据流斚w变得异常强大?/p> <p>  <em>l分的虚拟位U脓?Displacement Mapping with Tessellation)</em></p> <p>  几何着色器让虚拟位U脓囑֏以在GPU上生成。虚拟位U脓图是在离U渲染系l中非常行的一Ҏ术,它可以用一个简单的模型和高度图(Height Map)渲染出非常复杂的模型。高度图是一张用来表C模型上各点高度的灰度图。渲染时Q低多边形的模型会被l分成多边Ş更多的模型,再根据高度图上的信息Q把多边形挤出,来表现细节更丰富的模型?/p> <p>  而在DirectX 9中,GPU无法生成新的数据Q低多边形的模型无法被细分,所以只有小部分功能的虚拟位U脓囑֏以实现出来。现在,使用DirectX 10的强大力量,C千计的顶点可以凭I创造出来,也就实现了实时渲染中真正的细分的虚拟位移贴图?/p> <p>  <em>Z边缘(Adjacency)的新法</em></p> <p>  几何着色器可以处理三种囑օQ顶炏V线和三角Ş。同LQ它也可以输三种囑օ中的M一U,虽然每个着色器只能输出一U。在处理U和三角形时Q几何着 色器有取得边~信息的能力。用线和三角Ş边缘上的点Q可以实现很多强大的法。比如,边缘信息可以用来计算卡通渲染和真实毛发渲染的模型轮廓?/p> <p>  <em>式输出(Stream Output)</em></p> <p>  在DirectX 10之前Q几何体必须在写入内存之前被光栅化ƈ送入像素着色器(pixel shader)。DirectX 10引入了一个叫做数据流式输?Stream Output)的新Ҏ,它允许数据从点着色器或几何着色器中直接被传入帧缓冲内?Frame Buffer Memory)。这U输出可以被传回渲染水UK新处理。当几何着色器与数据流输出l合使用ӞGPU不仅可以处理新的囑Ş法Q还可以提高一般运和物理q算的效率?/p> <p>   在生成、删除数据和数据输些技术的支持下,一个完整的_子pȝ可以独立地在GPU上运行了。粒子在几何着色器中生成,在数据扩大的q程中被扩大与派生。新的粒子被数据输出到内存Q再被传回到点着色器制作动画。过了一D|_它们开始逐渐消失Q最后在几何着色器中被销毁?br></p> <h2>高渲染语言(HLSL 10)</h2> <p>  DirectX 10 Z前的DirectX 9中的“高着色语a”(High Level Shading Language )带来了诸多功能强大的新元素。其中包括可以提升常量更新速度?#8220;帔R~冲?#8221;(Constant Buffers)Q提升渲染流E中操作数据的灵zL的“视图”(view)Qؓ更广泛的法所准备?#8220;整数与位指o”(Integer and Bitwise Instructions)Q添加了switch语句?/p> <p>  <em>帔R寄存?Constant Buffers)</em></p> <p>  着色程序同普通的E序一样需要用常量来定义各种参数Q例如光源的位置和颜Ԍ摄像机的位置和投q阵以及一些材质的参数(例如反光?。在整个渲染的过E中Q这些常量往往需要频J的更新Q而数以百计的帔R的用以及更新无疑会lCPU带来极大的负载。DirectX 10中新加入的常量缓冲器可以Ҏ他们的用频率将q些帔R分配到指定的~冲器中q协调的对其q行更新?/p> <p>  在一个着色程序中DirectX 10支持最?6个常量缓冲器Q每一个缓冲器可以存放4096个常量。与其相比DirectX 9实在是少得可怜,因ؓ它在每个着色程序中同时最多只能支?56个常量?/p> <p align=center><img class=artimg alt=帔R着色器 src="http://www.highdiy.com/upimg/uploadimg/20061112/055617123.gif"></p> <p>  相比DirectX 9QDirectX 10不仅提供了更多的帔RQ最主要的是它大q的提升了常量更新的速度。对那些被分配到同一个缓冲器中的帔RQ我们只需q行一ơ操作就可以它们全部更新完毕,而非单个单个的去更新?/p> <p>  ׃不同的常量更新的旉间隔各异Q所以跟据用的频率来对他们q行l织可以获得更高的效率。D例来_摄像机的视矩阵只在每一帧之间发生改变,而类D图信息这L材质参数却会在图元切换时发生改变。于是这些常量缓冲器被分成了两个部分Q那些每帧更新的帔R~冲器专门存N些需要在两间更新的常数q在两间一ơ把他们全部更新Q另外的囑օ切换更新的常量缓冲器也同理。这样就会将更新帔Rq程中的一些不必要的工作消除,以便让整个着色器脚本比在 DirectX 9中运行的更加畅?/p> <em>视图(Views)</em> <p>  在DirectX 9中,着色器(shader)中的数据的类型是被严格划分开的。例如,点着色器用到的顶点缓冲器中的数据不能当作贴图的数据来让像素着色器使用。这样就特定的资源cd同其相对应的渲染程中的特定步骤紧密地结合了hQ同旉制了资源资源在整个渲染流E中可以使用的范围?/p> <p>  DirectX 10舍弃?#8220;严格区分的数据类?#8221;q一概念。当一D|据被创徏Q那么DirectX 10所做的仅仅是将其简单的当作内存中的一D区?bit field)来对待。如果要想用这一D|有定义类型的数据必通过使用一?#8220;view”?使用“view”Q相同的一D|据就可以有各U各LҎ来读取。DirectX 10支持对同一D资源在同时使用两个“view”?/p> <p>  通过q种多重“view”的手D,可以在整个渲染程的不同部分以不同目的使用同一D|据。例如:我们可以通过像素着色器一D几何数据渲染到一张纹?上,之后点着色器通过一?#8220;view”这张纹理视Z个顶点缓冲器q将其中的数据作为几何数据渲染?#8220;view”通过在整个渲染流E中的不同步骤重?使用同一D|据ؓ“数据处理”带来了更大的灉|性,帮助开发者实现更多更有创意更_ֽ的特效?/p> <p>  <em>整数与位q算指o(Integer and Bitwise Instructions)</em></p> <p>  在新的高U着色器语言中添加了“整数与位指o”Q这h“整数与位q算指o”的操作加入其基础q算函数的好处在于帮助一些算法在GPU上的实现。开发者终于可以直接用整数而非从Q点中{来计出准确的答案。数l的索引L在可以轻杄计算出来。GPU无整数运的时代l于被终l了。这ؓshader E序的开发带来很大的便利?/p> <p>  <em>Switch 语句(Switch Statement)</em></p> <p>  在DirectX 10中, HLSL可以支持switch语句Q这大q简化那些有着大量判断(分支)的着色器脚本的编码。一U用法就是徏立一?#8220;航母U的着色器(shader) E序”——包含了大量的小型着色器E序q且自n体Ş巨大的着色器E序。在q个“航母U的着色器E序”Q我们可以通过讑֮一个材质ID在switch语句?判断来轻杄在渲染同一个图元时切换不同的特效。也是_现在一个军队中的每个士兵n上都可以拥有各自不同的特效了?/p> <h2>DirectX 10的其他改q?/h2> <p>  <em>alpha to coverage</em></p> <p>  在游戏中Q经怋用带有半透明信息U理的多边Ş模型来模拟复杂的物体Q例如,草、树叶、铁丝网{。如果用真正的模型Q一颗边~参差不齐的草可能p消耗掉几百个多边ŞQ然而采用透明U理Q可以只??个多边Şp决了?/p> <p align=center><img class=artimg alt=半透明U理 src="http://www.highdiy.com/upimg/uploadimg/20061112/055643622.gif"><br>透明U理C意</p> <p>  然而,当用这U有半透明信息的纹理时候,它的不透明和透明部分的边界线上,常常会出现难看的锯。采用半透明混合技术可以解册个问题,但是它需要把场景中所有这cȝ体按照由q到q的序来绘Ӟ才能保证它们的遮挡关pL正确的,q会lCPU带来很大的压力,q不可取。在以前版本的DirectX中,alpha试和؜合简直就是图形程序员的噩梦?/p> <p>  在DirectX 10中,使用了一U新的技术叫做Alpha to coverage。用这U技术,在透明和不透明交界处的U理像素会被q行多极取样(Multi-sample)Q达到抗锯的效果。这在不引入大的性能开销的情况下单ƈ有效地解决了q个问题。室外场景的游戏大大受益于q种技术,树叶、铁丝网、草的边~将会更加柔和、圆滑?/p> <p align=center><img class=artimg alt="Alpha to coverage效果" src="http://www.highdiy.com/upimg/uploadimg/20061112/055657855.gif"><br>Alpha to coverage效果</p> <p>  <em>shadow map filtering</em></p> <p>  阴媄?Shadow map)技术已l逐渐成ؓ了渲染真实感阴媄的流行技术。在包括《战争机器》、《分裂细胞:双重特工》、《Ghost Recon》、《刺客信条》等的各大次世代游戏中都能看到它的n影。然而,׃shadow map的尺寔RӞ用它实现的阴p~往往有明昄锯。在DirectX 10中,提供了对shadow mapq行qo的功能的正式支持。经q过滤后Q阴q边缘会变得更加柔和?/p> <img src ="http://www.shnenglu.com/yuanyajie/aggbug/25201.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2007-05-31 15:11 <a href="http://www.shnenglu.com/yuanyajie/archive/2007/05/31/25201.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>const 用法一?/title><link>http://www.shnenglu.com/yuanyajie/archive/2007/05/14/24097.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Mon, 14 May 2007 07:56:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2007/05/14/24097.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/24097.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2007/05/14/24097.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/24097.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/24097.html</trackback:ping><description><![CDATA[<p><span style="COLOR: #0000ff">const 引用是指向const 对象的引?/span></p> <p>const int ival=1024;<br>const int &refVal=ival; //ok,both reference and object are const<br>int  &ref2=ival;        //error! non const reference to a const object<br>可以d但不能修改refVal,因此QQ何对refVal的赋值都是不合法的。这个限制有其意义:不能直接对ival同|因此不能通过使用refVal来修改ival?br>同理Q用ival初始化ref2也是不合法的Qref2是普通的非const引用Q因此可以用来修改ref2 指向的对象的倹{能qref2对ival赋gD修改const对象的倹{ؓLq样的修改,需?span style="COLOR: #ff00ff">规定普通的引用l定到const对象是不合法的?/span></p> <p><span style="COLOR: #ff00ff">const 引用可以初始化ؓ不同cd的对象或者初始化为右?/span>Q如字面值常量:<br>int i=42;<br>// legal for const reference ONLY!<br>const int &r=42;<br>const int &r2=r+i;</p> <p>double dval=3.14;<br>const int &r3=dval;<br>~译器展开Q?br>int temp=dval;<br>const int &ri=temp;</p> <p><span style="COLOR: #0000ff">非const引用只能l定C该引用同cd的对象?br>const引用则可以绑定到不同但相关的cd的对象或l定到右倹{?/span></p> <p>在C++中真正的临时对象是看不见的,它们不出现在你的源代码中。徏立一个没有命名的非堆Qnon-heapQ对象会产生临时对象。这U未命名的对象通常在两U条件下产生Q?span style="COLOR: #ff00ff">Z使函数成功调用而进行隐式类型{换和函数q回对象时?/span>理解如何和ؓ什么徏立这些时对象是很重要的Q因为构造和释放它们的开销对于E序的性能来说有着不可忽视的媄响?br>首先考虑Z函数成功调用而徏立时对象这U情c当传送给函数的对象类型与参数cd不匹配时会生这U情c?/p> <p>在字W计数的例子里,能够成功传递char数组到countChar中,但是在这里试囄char数组调用upeercasify函数Q则不会成功Q。考虑一下这个函敎ͼ<br>void uppercasify(string& str);<br>char subtleBookPlug[] = "Effective C++";<br>uppercasify(subtleBookPlug); // 错误!<br>没有Z调用成功而徏立时对象,Z么呢Q?br>假设建立一个时对象,那么临时对象被传递到upeercasify中,其会修改q个临时对象Q把它的字符Ҏ大写。但是对subtleBookPlug函数调用的真正参数没有Q何媄响;仅仅改变了时从subtleBookPlug生成的string对象。无疑这不是E序员所希望的。程序员传递subtleBookPlug参数到uppercasify函数中,期望修改subtleBookPlug的倹{当E序员期望修攚w临时对象Ӟ寚w帔R引用Qreferences-to-non-constQ进行的隐式cd转换却修改时对象?span style="COLOR: #ff00ff">q就是ؓ什么C++语言止为非帔R引用Qreference-to-non-constQ生时对象?/span>q样非常量引用(reference-to-non-constQ参数就不会遇到q种问题?br><br><span style="COLOR: #ff00ff">把一个const对象的地址赋给一个普通的Q非const对象的指针也会导致编译时错误</span>Q?br>const double pi=3.14;<br>double *ptr=&pi;   //error:ptr is a plain pointer<br>const double *cptr=&pi;  //ok:cptr is a pointer to const</p> <p><span style="COLOR: #ff00ff">不能使用void*指针保存const 对象的地址Q而必ȝconst void*cd的指针保存?/span><br>const int universe=42;<br>const void *cpv=&universe; //ok;<br>void *pv=&universe;      //error:universe is const</p> <p><span style="COLOR: #ff00ff">允许把非const 对象的地址赋给指向const 对象的指?/span>Q?br>double dval=3.14;<br>cptr=&dval;<br></p> typedef string *pstring;<br>const pstring cstr;<br>//cstr is a const pointer to string<br><span style="COLOR: #0000ff">string *const cstr  ; // equivalent to const pstring cstr; <br></span><br><br>Sales_item成员函数形参表后面的const后面所L作用:<span style="COLOR: #ff00ff">const 改变了隐含的this 形参的类?/span>。在调用<br>total.same_isbn(trans)Ӟ隐含的this形参是一个指向total对象的const Sales_item *cd的指针?br>׃this 是指向const对象的指针,const 成员函数不能修改调用该函数的对象?br><span style="COLOR: #ff00ff">const 对象Q指向const对象的指针或引用只能用于调用其const成员函数Q如果尝试用它们调用?br>const 成员函数</span>Q则是错误的? <img src ="http://www.shnenglu.com/yuanyajie/aggbug/24097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2007-05-14 15:56 <a href="http://www.shnenglu.com/yuanyajie/archive/2007/05/14/24097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用C++实现的一U插件体pȝ?----概述http://www.shnenglu.com/yuanyajie/archive/2007/04/17/22134.html清源游民清源游民Tue, 17 Apr 2007 07:54:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/04/17/22134.htmlhttp://www.shnenglu.com/yuanyajie/comments/22134.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/04/17/22134.html#Feedback8http://www.shnenglu.com/yuanyajie/comments/commentRss/22134.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/22134.html阅读全文

清源游民 2007-04-17 15:54 发表评论
]]>
类成员函数用做C回调函数http://www.shnenglu.com/yuanyajie/archive/2007/03/30/20945.html清源游民清源游民Fri, 30 Mar 2007 08:10:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2007/03/30/20945.htmlhttp://www.shnenglu.com/yuanyajie/comments/20945.htmlhttp://www.shnenglu.com/yuanyajie/archive/2007/03/30/20945.html#Feedback4http://www.shnenglu.com/yuanyajie/comments/commentRss/20945.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/20945.html 提出问题Q?/font>
回调函数是基于C~程的Windows SDK的技术,不是针对C++的,E序员可以将一个C函数直接作ؓ回调函数Q但是如果试囄接用C++的成员函C为回调函数将发生错误Q甚至编译就不能通过?br />分析原因Q?/font>
普通的C++成员函数都隐含了一个传递函C为参敎ͼ亦即“this”指针,C++通过传递一个指向自w的指针l其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解ؓ什么C++cȝ多个实例可以׃n成员函数但是有不同的数据成员。由于this指针的作用,使得一个CALLBACK型的成员函数作ؓ回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失?br />解决ҎQ?/font>
一,不用成员函敎ͼ直接使用普通C函数Qؓ了实现在C函数中可以访问类的成员变量,可以使用友元操作W?friend)Q在C++中将该C函数说明?font color="#ff1493">cȝ
友元卛_。这U处理机制与普通的C~程中用回调函C栗?br />?使用静态成员函?/font>Q静态成员函C使用this指针作ؓ隐含参数Q这样就可以作ؓ回调函数了。静态成员函数具有两大特点:其一Q可以在没有cd例的情况下用;其二Q只能访问静态成员变量和静态成员函敎ͼ不能讉K非静态成员变量和非静态成员函数。由于在C++中用类成员函数作ؓ回调函数的目的就是ؓ了访问所有的成员变量和成员函敎ͼ如果作不到这一点将不具有实际意义。我们通过使用静态成员函数对非静态成员函?font color="#ff1493">包装的办法来解决问题。类实例可以通过附加参数?font color="#ff1493">全局变量
的方式的方式传递到静态成员函C。分别D例如下:
1Q参C递的方式
   #include <iostream.h>  
   class TClassA
   {
   public:

      void Display(const char* text) { cout << text << endl; };
      static void Wrapper_To_Call_Display(void* pt2Object, char* text);
      // more....
   };

   // 静态包装函敎ͼ能够调用成员函数Display(),本n做ؓ回调函数来?/font>
   void TClassA::Wrapper_To_Call_Display(void* pt2Object, char* string)
   {
       // 昑ּcd转换
       TClassA* mySelf = (TClassA*) pt2Object;

       // 调用普通成员函?br />       mySelf->Display(string);
   }

   // 回调函数的宿?在这里回调用函数被?br />   void DoItA(void* pt2Object, void (*pt2Function)(void* pt2Object, char* text))
   {
      // 使用回调函数
      pt2Function(pt2Object, "hi, i'm calling back using a argument ;-)"); 
   }

   // 执行CZ
   void Callback_Using_Argument()
   {
      TClassA objA;
      DoItA((void*) &objA, TClassA::Wrapper_To_Call_Display);
   }

2Q全局变量的方?br />   #include <iostream.h>  
   void* pt2Object;        // 全局变量,可以指向L对象
   class TClassB
   {
   public:

      void Display(const char* text) { cout << text << endl; };
      static void Wrapper_To_Call_Display(char* text);

   };

   // 静态的包装函数
   void TClassB::Wrapper_To_Call_Display(char* string)
   {
       //需要保证全局变量值的正确?br />       TClassB* mySelf = (TClassB*) pt2Object;
       mySelf->Display(string);
   }

   // 回调用函数的宿主,在这里回调用函数被?br />   void DoItB(void (*pt2Function)(char* text))
   {
  
      pt2Function("hi, i'm calling back using a global ;-)");   // make callback
   }

   // 执行CZ
   void Callback_Using_Global()
   {
      TClassB objB;  
      pt2Object = (void*) &objB;
      DoItB(TClassB::Wrapper_To_Call_Display);
   }

注意Q通过上面两种Ҏ的比较可以看出,W?U方法中静态包装函数可以和普通成员函C持签名一_当回调函数的宿主接口不能改变Ӟq种Ҏ特别有用。但因ؓ使用了全局变量Q也不是一个好的设计?/p>

 


 



清源游民 2007-03-30 16:10 发表评论
]]>
game c++http://www.shnenglu.com/yuanyajie/archive/2006/12/27/16910.html清源游民清源游民Wed, 27 Dec 2006 07:35:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2006/12/27/16910.htmlhttp://www.shnenglu.com/yuanyajie/comments/16910.htmlhttp://www.shnenglu.com/yuanyajie/archive/2006/12/27/16910.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/16910.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/16910.html  如果有一个好的编译器Q再加上对语a的了解,真的有可能用C++写出一些有效率的游戏程序来。本文描qC典型的几U你可以用来加速游戏的技术。它假设你已l非常肯定用C++的好处,q且你也对优化的基本概念相当熟悉?br />  W一个经常让益的基本概念昄是剖析(profilingQ的重要性。缺乏剖析的话,E序员将犯两U错误,其一是优化了错误的代码:如果一个程序的主要指标不是效率Q那么一切花在其更高效上的旉都是费。靠直觉来判断哪D代码的主要指标是效率是不可信的Q只有直接去量。第二个概念是程序员l常 "优化"到降低了代码的速度。这在C++是一个典型问题,一个简单的指o行可能会产生巨大数量的机器代码,你应当经常检查你的编译器的输出,q且剖析之?br />1、对象的构造与析构
  对象的构造与析构是C++的核心概念之一Q也是编译器背着你生代码的一个主要地斏V未l认真设计的E序l常p不少旉在调用构造函敎ͼ拯对象以及初始化时对象等{。幸q的是,一般的感觉和几条简单的规则可以让沉重的对象代码跑得和C只有毫厘之差?br />  除非需要否则不构造?br />  最快的代码是根本不q行的代码。ؓ什么要创徏一个你Ҏ不去使用的对象呢Q在后面的代码中Q?br />
  voide Function(int arg)
  {
    Object boj;
    If(arg==0)
      Return;
    ...
  }

  即便arg?Q我们也付出了调用Object的构造函数的代h。特别是如果argl常?Qƈ且Object本nq分配内存,q种费会更加严重。显然的Q解x案就是把obj的定义移到判断之后?br />  心在@环中定义复杂变量Q如果在循环中按照除非需要否则不构造的原则构造了复杂的对象,那么你在每一ơ@环的时候都要付Zơ构造的代h。最好在循环外构造之以只构造一ơ。如果一个函数在内@环中被调用,而该函数在栈内构造了一个对象,你可以在外部构造ƈ传递一个应用给它?br />
  1.1 采用初始化列?br />  考虑下面的类Q?br />
  class Vehicle
  {
  public
    Vehicle(const std::string &name)
    {
      mName=name
    }
  private:
    std::string mName;
  }

  因ؓ成员变量会在构造函数本体执行前构造,q段代码调用了string mName的构造函敎ͼ然后调用了一?操作W,来拷贝其倹{这个例子中的一个典型的不好之处在于string的缺省构造函C分配内存Q但实际上都会分配大大超q实际需要的I间。接下来的代码会好些Qƈ且阻止了?操作W的调用Q进一步的来说Q因为给Z更多的信息,非缺省构造函C更有效,q且~译器可以在构造函数函C为空的情况下其优化掉?br />
  class Vehicle
  {
  public
    Vehicle(const std::string &name):mName(name)
    { }
  private:
    std::string mName;
  }

  1.2 要前自增不要后自增(卌++I不要I++Q?br />  当写x=y++时生的问题是自增功能将需要制造一个保持y的原值的拯Q然后y自增Qƈ把原始的D回。后自增包括了一个时对象的构造,而前自增则不要。对于整敎ͼq没有额外的负担Q但对于用户自定义类型,q就是浪费,你应该在有可能的情况下运用前自增Q在循环变量中,你会帔R到这U情形?br />  不用有q回值的操作W?在C++中经常看到这样写点的加法:

  Vector operator+(const Vector &v1,const Vector &v2)

  q个操作引赯回一个新的Vector对象Q它q必被以值的形式q回。虽然这样可以写v=v1+v2q样的表辑ּQ但象构造时对象和对象的拷贝这L负担Q对于象点加法q样常被调用的事情来说太大了一炏V有时候是可以好好规划代码以ɾ~译器可以把临时对象优化掉(q一点就是所谓的q回g化)。但是更普遍的情形下Q你最好放下架子,写一炚w看但更快速的代码Q?br />
  void Vector::Add(const Vector &v1,const Vector &v2)

  注意+=操作Wƈ没有同样的问题,它只是修改第一个参敎ͼq不需要返回一个时对象,所以,可能的情况下Q你也可以用+=代替+?br />
  1.3 使用轻量U的构造函?br />  在上一个例子中Vector的构造函数是否需要初始化它的元素?Q这个问题可能在你的代码中会有好几处出现。如果是的话Q它使得无论是否必要Q所有的调用都要付初始化的代仗典型的来说Q旉点以及成员变量就会要无辜的承受这些额外的开销?br />  一个好的编译器可以很好的移除一些这U多余的代码Q但是ؓ什么要冒这个险呢?作ؓ一般的规则Q你希望构造函数初始化所有的成员变量Q因为未初始化的数据生错误。但是,在频J实例化的小cMQ特别是一些时对象,你应该准备向效率规则妥协。首选的情况是在许多游戏中有的vector和Matrix c,q些cL然应当提供一些方法置0和识别,但它的缺省构造函数却应当是空的?br />  q个概念的推论就是你应当U类提供另一个构造函数。如果我们的W二个例子中的VebiclecLq样写的话:

  class Vehicle
  {
  public:
    vehicle()
    {
    }
    void SetName(const std::string &name)
    {
      mName=name;
    }
  private:
    std::string mName
  };

  我们省去了构造mName的开销Q而在E后用SetNameҎ讄了其倹{相似的Q用拷贝构造函数将比构造一个对象然后用=操作W要好一些。宁愿这h构造:Vebicle V1(V2)也不要这h构造:

  Vehicle v1;v1=v2;

  如果你需要阻止编译器帮你拯对象Q把拯构造函数和操作W?声明为私有的Q但不要实现其中M一个。这PM企图对该对象的拷贝都生一个编译时错误。最好也L定义单参数构造函数的习惯Q除非你是要做类型{换。这样可以防止编译器在做cd转换时生的隐藏的时对象?br />
  1.4 预分配和Cache对象
  一个游戏一般会有一些类会频J的分配和释放,比如武器什么的。在CE序中,你会分配一个大数组然后在需要的时候用。在C++中,l过小的规划以后,你也可以q样qӀ这个方法是不要一直构造和析构对象而是h一个新而把旧的q回lCache。Cache可以实现成一个模板,它就可以为所有的有一个缺省构造函数的cd作。Cache模板的Sample可以在附带的CD中找到?br />  你也可以在需要时分配一些对象来填充CacheQ或者预先分配好。如果你q要对这些对象维护一个堆栈的话(表示在你删除对象X之前Q你先要删除所有在X后面分配的对象)Q你可以把Cache分配在一个连l的内存块中?br />
2、内存管?br />  C++应用E序一般要比CE序更深入到内存理的细节。在C中,所有的分配都简单的通过malloc和free来进行,而C++则还可以通过构造时对象和成员变量来隐式的分配内存。很多C++游戏E序需要自q内存理E序。由于C++游戏E序要执行很多的分配Q所以要特别心堆的片。一个方法是选择一条复杂的路:要么在游戏开始后Ҏ不分配Q何内存,要么l护一个巨大的q箋内存块,q按期释放(比如在关卡之_。在C机器上,如果你想对你的内存用很警惕的话Q很严格的规则是没必要的?br />  W一步是重蝲new?Delete操作W,使用自己实现的操作符来把游戏最l常的内存分配从malloc定向到预先分配好的内存块去,例如Q你发现你Q何时候最多有10000 ?字节的内存分配,你可以先分配?0000字节Q然后在需要时引用出来。ؓ了跟t哪些块是空的,可以l护一个由每一个空的块指向下一个空的块的列?free list。在分配的时候,把前面的blockULQ在释放的时候,把这个空块再攑ֈ前面厅R图1描述了这个free list如何在一个连l的内存块中Q与一pd的分配和释放协作的情形?br />

? A linked free list
[img]http://mays.soage.com/develop/optimize/200112/image/Other/OptFORCGame.gif[/img]

  你可以很Ҏ的发C个游戏是有着许多小的生命短暂的内存分配Q你也许希望为很多小块保留空间。ؓ那些现在没有使用到的东西保留大内存块会浪费很多内存。在一定的寸上,你应当把内存分配交给一支不同的大内存分配函数或是直接交lmalloc()?br />
3、虚函数
  C++游戏E序的批评者L把矛头对准虚函数Q认为它是一个降低效率的秘Ҏ。概忉|的_虚函数的机制很简单。ؓ了完成一个对象的虚函数调用,~译器访问对象的虚函数表Q获得一个成员函数的指针Q设|调用环境,然后跌{到该成员函数的地址上。相对于CE序的函数调用,CE序则是讄调用环境Q然后蟩转到一个既定的地址上。一个虚函数调用的额外负担是虚函数表的间接指向;׃事先q不知道要跌{的地址Q所以也有可能造成处理器不能命中Cache?br />  所有真正的C++E序都对虚函数有大量的用,所以主要的手段是防止在那些极其重视效率的地方的虚函数调用。这里有一个典型的例子Q?br />
  Class BaseClass
  {
  public:
    virtual char *GetPointer()=0;
  };

  Class Class1: public BaseClass
  {
    virtual char *GetPointer();
  };

  Class Class2:public BaseClass
  {
    virtual char *GetPointer();
  };

  void Function(BaseClass *pObj)
  {
    char *ptr=pObj->GetPointer();
  }

  如果Function()极其重视效率Q我们应当把GetPointer从一个虚函数Ҏ内联函数。一U方式是lBaseClass增加一个新的保护的数据成员Q在每一个类中设|该成员的|在GetPointerq个内联函数中返回该成员l调用者:

  Class BaseClass
  {
  public:
    inline char GetPointerFast()
    {
      return mpPointer;
    }
  protected:
    inline void SetPointer(char *pData)
    {
      mpData = pData;
    }
  private:
    char *mpData;
  };

  void Function(BaseClass *pObj)
  {
    char *ptr= pObj->GetPointerFast();
  }

  一个更Ȁq的Ҏ是重新规划你的类l承树,如果Class1和Class2只有一点点不同Q那么可以把它们捆绑到同一个类中去Q而用一个Flag来表明它象Class1q是象Class2一样工作,同时在BaseClass中把U虚函数L。这L话,也可以象前面的例子一hGetPointer写成内联。这U变通看h不是很高雅,但是在缺Cache的机器上跑内循环Ӟ你可能会很愿意ؓ了去掉虚函数调用而把事情做得更加隄?br />  虽然每一个新的虚函数都只l每个类的虚表增加了一个指针的寸Q通常是可以忽略的代hQ,W一个虚函数q是在每一个对象上要求了一个指向虚表的指针。这是说你在很的、频J用的cM使用M虚函数而造成了额外的负担Q这些都是不能接受的。由于承一般都要用C个或几个虚函敎ͼ臛_有一个虚的析构函敎ͼQ所以你没必要在而频J用的对象上用Q何ѝ?br />
4、代码尺?br />  ~译器因为C++产生冗长的代码而臭名昭著。由于内存有限,而小的东西往往是快的,所以你的可执行文件尽可能的小是非帔R要的。首先可以做的事情是拿一个编译器来研I。如果你的编译器会在可执行文件中保存 Debug信息的话Q那么把它们U除掉。(注意MS VC会把Debug信息攑֜可执行文件外部,所以没关系Q异常处理会产生额外的代码,可能的去除异常处理代码。确保连接器配置为去除无用的函数和类。开启编译器的最高优化别,q尝试设|ؓ寸最化而不是速度最大化 ?有时候,׃Cache命中的提高,会生更好的q行效果。(注意在用这设|时查instrinsic功能是否也处于打开状态)L所有Debug 输出状态下的浪费空间的字符Ԍ使编译器把多个相同的字符串捆l成一个实例?br />  内联通常是造成大函数的首犯。编译器可以自由的选择注意或忽略你写的inline关键字,而且它们q会背着你制造一些内联。这是另一个要你保持轻量的构造函数的原因Q这样堆栈中的对象就不会因ؓ有大量的内联代码而膨胀。同时也要小心重载运符Q即使是最短的表达式如m1=m2*m3如果m2和m3是矩늚话,也可能生大量的内联代码。一定要深入了解你的~译器对于内联的讄?br />  启用q行时类型信息(RTTIQ需要编译器为每一个类产生一些静态信息。RTTI一般来说是~省启用的,q样我们的代码可以调用dynamic_cast以及一个对象的cdQ考虑完全止使用RTTI和dynamic_cast以节省空_q一步的_有时?dynamic_cast在某些实C需要付出很高的代hQ另一斚wQ当你真的需要有Zcd的不同行为的时候,增加一个不同行为的虚函数。这是更好的面向对象设计Q注意static_cast与这不同Q它的效率和C语言的类型{换一P?br />
5、标准类库(STLQ?br />  标准cd是一套实C常见的结构和法的模板,例如dynamic arraysQ称为vectorQ,setQmap{等。用STL可以节省你很多时间来写和调试那些容器。和之前谈到的一P如果希望pȝ的效率最大化Q你必须要注意你的STL的具体实现的l节?br />  Z能够对应于最大范围的应用QSTL标准在内存分配这个领域保持了沉默。在STL容器中的每一个操作都有一定的效率保证Q例如,l一个setq行插入操作只要O(log n)的时_但是Q对一个容器的内存使用没有M保证?br />  让我们来仔细了解游戏开发中的一个非常普遍的问题Q你希望保存一l对象,Q我们会U其为对象列表,虽然不一定要保存在STL的列表中Q通常你会要求每个对象在这个表有且仅有一个,q样你就不用担心一个偶然生的在容器中插入一个已存在单元的操作了。STL的set忽略副本Q所有的插入、删除和查询的速度都是O(log n)Q这是不是就是很好的选择呢?
  虽然在set上的大多数操作的速度都是O(log n)Q但是这里面依然存在着潜在的危机。虽然容器的内存使用依赖于实玎ͼ但很多实现还是在U黑树的基础上实现的。在U黑树上Q树的每一个节炚w是容器的一个元素。常见的实现Ҏ是在每一个元素被加入到树Ӟ分配一个节点,而当每个元素被移出树Ӟ释放一个节炏V根据你插入和删除的频繁E度Q在内存理器上所p的时间将或多或少的媄响你通过使用set而获得的好处?br />  另外一个解x案是使用vector来存储元素,vector保证在容器的末端d元素有很高的效率。这表示实际上vector只在很偶然的情况下才重新分配内存Q也是_当满的时候扩容一倍。当使用vector来保存一个不同元素列表的时候,你首先要查元素是否已l存在,如果没有Q那么加入。而对整个vector查一遍需要花费O(n)的时_但是但实际牵涉到的部分应该比较少Q这是因为vector的每个元素都在内存中q箋存放Q所以检查整个vector实际上是一个易于cache的操作。检查整个set造成cache 不命中,q是因ؓ在红黑树上分别存攄元素可能散布在内存的各个角落。同Ӟ我们也注意到set必须额外l护一l标C讄整个树。如果你要保存的是对象的指针Qset可能要花费vector所要花费的内存??倍?br />  Set的删除操作消耗时间O(log n)Q看h是很快,如果你不考虑可能对free()的调用的话。Vector的删除操作消耗O(n)Q这是因Z被删除的那个元素开始到l尾处的元素Q每一个元素都要被拯到前一个位|上。如果元素都只是指针的话Q那么这个拷贝将可以依靠一个简单的memcpy()来完成,而这个函数是相当快的。(q也是ؓ什么通常都把对象的指针储存在STL的容器中的一个原因,而不是储存对象本w。如果你直接保存了对象本w,会在很多操作中造成许多额外的构造函数的调用Q例如删除等Q?br />  set和map通常来说ȝ大于有用Q如果你q没有意识到q一点的话,考虑遍历一个容器的代hQ例如:

  for(Collection::iterator it = Collection.begin(); it != Collection.end(); ++it)

  如果Collection是vectorQ那?+it是一个指针自增。但是当Collection是一个set或者是一个map的话Q?+it包括了访问红黑树上的下一个节炏V这个操作相当复杂而且很容易造成cache不命中,因ؓ树的节点几乎遍布内存的各处?br />  当然Q如果你要在容器中保存大量的元素Qƈ且进行许多的成员hQ那么set的O(log n)的效率完全可以抵消那些内存方面的消耗。近似的Q如果你偶尔才用容器,那么q里的效率差别就非常的小。你应该做一些效率评C了解多大的n会 set变得更快。也怽会惊奇的发现在游戏的大多数典型应用下vector的所有效率都比set要高?br />  q还不是STL内存使用的全部。一定要了解当你使用clearҎӞ容器是否真的释放掉了它的内存。如果没有,可能生内存碎片。比如,如果你开始游戏的时候徏立了一个空的vectorQ在游戏q程中增加元素,然后在游戏restart时调用clearQ这时vector未必释放它的全部内存。这个空的vectorQ可能依然占据了堆中的内存,q其变成碎片。如果你真的需要这h实现游戏的话Q对q个问题有两U解法。一是你可以在创建vector时调用reserve()Qؓ你可能需要的最大数量的元素保留_的空间。如果这不可行的话,你可以强qvector完全释放内存Q?br />
  Vector V;
  // ... elements are inserted into V here
  Vector().swap(v);  // causes v to free its memory

  Set、list以及map都没有这个问题,q是因ؓ他们为每个元素分别分配和释放内存?br />
6、高U特?br />  ~程语言的某些特性你可能没必要用到。看上去单的Ҏ可能会D低下的效率。而看h复杂的特性没准执行得很好。C++的这些黑暗角落异怾赖于~译器。当你要使用它们Ӟ必须了解它们的代仗?br />  C++的string是一个看h不错的例子,但是在效率极光要的场合应该避免使用Q考虑下面的代码?br />
  Void Function(const std::string &str)
  {
  }
  Function("hello");

  对Function()的调用包括了对给定const char*参数的构造函数的调用。在普遍的实CQ这个构造函数执行了一个malloc()Q一个strlen()Q以及一个memcpy()Q而析构函数立M来做了一些无意义的事情。(׃该例子中的string没有被更多的应用Q然后又跟了一个free()。这里的内存分配完全是浪费,因ؓ字符?"hello"早就在程序的数据D中了。我们早有它在内存中的副本了。如果Function定义了一个const char*的参敎ͼ那么完全没有了上面所说的那些额外的调用。这是Z使用方便的string而付出的高昂代h?br />  模板是效率的对立面的一个例子,Ҏ语言标准Q编译器在模板实例化Z个具体的cd时生代码。理ZQ看上去是声明了一个模板,但却实际产生了大量的怼的代码。如果你有了 class1的指针的vectorQ也有class2的指针的vectorQ你在你的可执行文件中做了两䆾的vector的拷贝?br />  事实上,大多数的~译器做得更好,首先Q只有实际被使用到的模板成员函数被生代码。其ơ,如果事先了解了正的行ؓQ编译器可以只生一份代码的拯。你可以从vector的例子发现这一点,实只生了一份代码(一般是vectorQ。有了好的编译器Q模板还是可以在保持高效的同时提供你一般编E的好处?br />  C++的一些特性,比如初始化列表以及前自增Q一般来说可以提高效率。而象其它的一些特性比如运符重蝲以及RTTI则看hg是清白的Q但却有时带来严重的效率问题。STL的容器则描述了盲目相信函数的法q行旉可以如何让你误入歧途。避免用潜在的低效率的语言或类库特性,同时׃旉来了解你的编译器的各U选项。你会很快的学会设计高效的代码,q且解决掉你的游戏中的效率问题?br />

清源游民 2006-12-27 15:35 发表评论
]]>
(转)剖析C++标准库智能指?std::auto_ptr) http://www.shnenglu.com/yuanyajie/archive/2006/12/15/16489.html清源游民清源游民Fri, 15 Dec 2006 09:35:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2006/12/15/16489.htmlhttp://www.shnenglu.com/yuanyajie/comments/16489.htmlhttp://www.shnenglu.com/yuanyajie/archive/2006/12/15/16489.html#Feedback1http://www.shnenglu.com/yuanyajie/comments/commentRss/16489.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/16489.html阅读全文

清源游民 2006-12-15 17:35 发表评论
]]>
如何float转换为string http://www.shnenglu.com/yuanyajie/archive/2006/12/15/16476.html清源游民清源游民Fri, 15 Dec 2006 03:18:00 GMThttp://www.shnenglu.com/yuanyajie/archive/2006/12/15/16476.htmlhttp://www.shnenglu.com/yuanyajie/comments/16476.htmlhttp://www.shnenglu.com/yuanyajie/archive/2006/12/15/16476.html#Feedback0http://www.shnenglu.com/yuanyajie/comments/commentRss/16476.htmlhttp://www.shnenglu.com/yuanyajie/services/trackbacks/16476.html
 

     可能有好多hQ包括C语言老手都不知道如何float数据转换为stringQ我是q样Q今天查了一下MSDNQ才知道C提供了_gcvt函数实现q个功能Q收L实不,Z方便自己查询Q也Z那些像我q样的网友能够了解该函数的具体用法,我把MSDN的原文原不动抄录如下:

_gcvt

Converts a floating-point value to a string, which it stores in a buffer.

char *_gcvt( double value , int digits , char * buffer );

Routine Required Header Compatibility
_gcvt <stdlib.h> Win 95, Win NT

For additional compatibility information, see Compatibility in the Introduction.

Libraries

LIBC.LIB Single thread static library, retail version
LIBCMT.LIB Multithread static library, retail version
MSVCRT.LIB Import library for MSVCRT.DLL, retail version

Return Value

_gcvt returns a pointer to the string of digits. There is no error return.

Parameters

value

Value to be converted

digits

Number of significant digits stored

buffer

Storage location for result

Remarks

The _gcvt function converts a floating-point value to a character string (which includes a decimal point and a possible sign byte) and stores the string in buffer. The buffer should be large enough to accommodate the converted value plus a terminating null character, which is appended automatically. If a buffer size of digits + 1 is used, the function overwrites the end of the buffer. This is because the converted string includes a decimal point and can contain sign and exponent information. There is no provision for overflow. _gcvt attempts to produce digits digits in decimal format. If it cannot, it produces digits digits in exponential format. Trailing zeros may be suppressed in the conversion.

Example

								/* _GCVT.C: This program converts -3.1415e5 * to its string representation. */#include <stdlib.h>#include <stdio.h>void main( void ){   char buffer[50];   double source = -3.1415e5;   _gcvt( source, 7, buffer );   printf( "source: %f  buffer: '%s'\n", source, buffer );   _gcvt( source, 7, buffer );   printf( "source: %e  buffer: '%s'\n", source, buffer );}
						

Output

								source: -314150.000000  buffer: '-314150.'source: -3.141500e+005  buffer: '-314150.'
						


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=708935





#  lanno 发表?006-05-05 18:26:00  IP: 222.35.68.*
长见识了Q俺Lq样转化的:
char str[260];
float f = -3.1415926;
float f1 = 263e-5;
sprintf(str,"%f",f);
printf("%s\n",str);
sprintf(str,"%f",f1);
printf("%s\n",str);

#  Skyman 发表?006-05-05 21:35:00  IP: 202.202.10.*
你这样做也行
但没有这Lz?
是吧Q?/div>

#  zhnde 发表?006-05-11 20:15:00  IP: 129.69.212.*
灉|吗? 能具体解释一下吗Q?/div>

#  Skyman 发表?006-05-11 22:03:00  IP: 202.202.10.*
臛_可以方便的控制有效数字的位数啊?/div>

#  ztwaker 发表?006-07-28 12:40:00  IP: 61.144.207.*
/*C++ impl*/
string cvt(const float fval)
{
stringstream ss;
ss << fval;
return ss.str();
}

......///

#  ztwaker 发表?006-07-28 12:46:00  IP: 61.144.207.*
加上有效数字位数控制

string cvt(const float f, const int prec)
{
stringstream ss;
ss.precision(prec);
ss << f;
return ss.str();
}



清源游民 2006-12-15 11:18 发表评论
]]>头文件包含问?/title><link>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16445.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Thu, 14 Dec 2006 10:16:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16445.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/16445.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16445.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/16445.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/16445.html</trackback:ping><description><![CDATA[ <div id="9jd9d9n" class="postTitle"> <a > <img height="13" src="http://blog.csdn.net/images/zhuan.gif" width="15" border="0" /> C++中基cM相引用带来的问题</a> </div> <div id="lfp3p3j" class="postText"> <p> <font size="3">在一些大的工E中Q可能会包含几十个基c,免不了之间会互相引用</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">(</span> </font> <font size="3">不满承关p,而是l合关系</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">)</span> </font> <font size="3">。也是需要互相声明。好了,q时候会带来一些؜乱。如果处理得不好Q会搞得一团糟Q根据我的经验,单谈谈自已的处理办法Q?/font> </p> <p> <font size="3">~码Ӟ我们一般会量避免</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">include</span> </font> <font size="3">头文Ӟ而是采用声明 </font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">class XXX</span> </font> <font size="3">?/font> <font size="3">但有时候还是必ȝ</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">Include</span> </font> <font size="3">头文Ӟ那么Q两者的划分在于什么呢Q?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br /> <br /> </span> </font> <font size="3">应该是很明确的,但书上好像都有提及?/font> </p> <p> <font size="3">首先Q?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br /> </span> </font> <font size="3">我们要明白ؓ什么要用声明取代头文g包含Q对了,是ؓ了避免无必要的重~译</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">(</span> </font> <font size="3">在头文g发生变更?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">)</span> </font> <font size="3">?/font> <font size="3">工程较大Q低速机Q或基础cȝ常变?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">(</span> </font> <font size="3">不合理的设计?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">)</span> </font> <font size="3">Q编译速度q是会在意的Q?/font> <font size="3">另外Q更为重要的是,采用声明可降低代?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">(class)</span> </font> <font size="3">之间的藕合度Q这也是面向对象设计的一大原则?/font> </p> <p> <font size="3">二:一般原则:</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br />a. </span> </font> <font size="3">头文件中量?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">include, </span> </font> <font size="3">如果可以单申?</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">class clsOld; </span> </font> <font size="3">解决Q那最好。减没有必要的</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">includeQ?br />b. </span> </font> <font size="3">实现文g中也要尽量少</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">include,</span> </font> <font size="3">不要</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">include</span> </font> <font size="3">没有用到的头文g?</font> </p> <p> <font size="3">三:那什么时候可以只是简单声?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">class clsOld</span> </font> <font size="3">呢?</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br /> </span> </font> <font size="3">单的_不需要知?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">clsOld</span> </font> <font size="3">的内存布局的用法都可以</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">(</span> </font> <font size="3">静态成员除?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">)</span> </font> <font size="3">Q也是讲如果是指针或引用方式的</font> <font size="3">都行?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br /> </span> </font> <font size="3">比如Q?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br />   clsOld * m_pOld;    //</span> </font> <font size="3">指针?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">4</span> </font> <font size="3">个字节长</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br />   clsOld & test(clsOld * pOld) {return *pOld};<br />  </span> </font> <font size="3">一?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">OK</span> </font> <font size="3">?/font> </p> <p> <font size="3">四:什么时候不能简单声?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">class clsOld</span> </font> <font size="3">Q必?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">include</span> </font> <font size="3">呢?</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br /> </span> </font> <font size="3">不满三的情况下Q?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br /> </span> </font> <font size="3">比如Q?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br />         clsOld m_Objold;  //</span> </font> <font size="3">不知道占据大,必须要通过它的具体声明来计?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br /> </span> </font> <font size="3">原因很简单,x你要计算</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">sizeof(classNew)</span> </font> <font size="3">Q但q?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">clsOld</span> </font> <font size="3">?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">size</span> </font> <font size="3">都不知道Q编译器昄会无能ؓ力?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br /> <br /> </span> </font> <font size="3">Ҏ情况Q?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br />          int test() { return clsOld::m_sInt;}<br />    </span> </font> <font size="3">静态成员调用,x应该是不需要知道内存布局的,但因为需要知?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">m_sInt</span> </font> <font size="3">是属?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">clsOld</span> </font> <font size="3">命名I间</font> <font size="3">的,如果只声?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">class xxx</span> </font> <font size="3">昄是不以说明的,所以必d含头文g?/font> </p> <p> <font size="3">lg所qͼ我有以下几点Q?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> <br />1</span> </font> <font size="3">Q如果有共同相关依赖</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">(</span> </font> <font size="3">必须</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">include)</span> </font> <font size="3">的类Q比?</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">A,B</span> </font> <font size="3">都依?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">D </span> </font> <font size="3">可以攑֜一P然后直接 </font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">Include "d" </span> </font> <font size="3">cȝ使用者只需兛_与本cL露出的相关类型,内部用到的类型不用去?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">(</span> </font> <font size="3">不用自已?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">include d)</span> </font> <font size="3">。这?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> </span> </font> <font size="3">l出?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">class</span> </font> <font size="3">Q调用者才更好?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">(</span> </font> <font size="3">不用ȝ代码查找Q是不是q需要包含其它头文g</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">)</span> </font> <font size="3">?/font> </p> <p> <font face="Times New Roman, serif" size="3"> <span lang="en-US">2</span> </font> <font size="3">Q如?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">A</span> </font> <font size="3">cM?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">D B</span> </font> <font size="3">cM依赖</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">D</span> </font> <font size="3">Q可以把它们分开两个头文件。各?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">Include</span> </font> <font size="3">。这样可避免?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">D</span> </font> <font size="3">发生变化Ӟ</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> </span> </font> <font size="3">避免不必要重~译?/font> </p> <p> <font face="Times New Roman, serif" size="3"> <span lang="en-US">3</span> </font> <font size="3">Q类中尽量采用指针或引用方式调用其它c,q样可以只声明</font> <font face="Times New Roman, serif" size="3"> <span lang="en-US">class xxx</span> </font> <font size="3">了。ƈ且这也符合资源最?/font> <font face="Times New Roman, serif" size="3"> <span lang="en-US"> </span> </font> <font size="3">利用Q更利于使用多态?br /><br />/--------------------------------------------------/////////////////////////////////////////////////////////////////////////////<br /></font> </p> <div id="hjvrlbh" class="postTitle"> <a > <img height="13" src="http://blog.csdn.net/images/authorship.gif" width="15" border="0" /> <font color="#009933"> 对于VC++中的头文件包含值得注意的一?/font> </a> </div> <div id="vxrvp1r" class="postText"> <p class="MsoNormal" style="MARGIN-BOTTOM: 15.6pt"> <span style="FONT-FAMILY: 宋体">  </span> <span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">今天?span lang="EN-US">VC++</span>~译我这昨天写的代码时发现L通不q,看到大部分的错误都是与一个类的定义有兟?span lang="EN-US"><?XML:NAMESPACE PREFIX = O /?><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN-BOTTOM: 15.6pt"> <span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">  明明我已l在q个cM定义了一个成员变量,可编译器偏要说那个变量不是这个类的成员。没办法Q找了半天原因还是没有头l。再三地认不是?span lang="EN-US">C++</span>的语法错误之后。我开始怀疑是不是头文件的问题。因为当我把一?strong><span lang="EN-US">#include "..."</span></strong>搬到<strong><span lang="EN-US">#pragma once</span></strong>之前或者之后,错误报告׃发生变化。有时就只是说我的一个类<strong>重复定义</strong>了?span lang="EN-US"><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN-BOTTOM: 15.6pt; TEXT-INDENT: 24pt"> <span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">以前?span lang="EN-US">C</span>写头文g的时候都是用宏定义来避免重复包含<strong>头文?/strong>?span lang="EN-US">C++</span>里虽然也q可用这个方法,?span lang="EN-US">VC++</span>是不用Q它用的?strong><span lang="EN-US">#pragma once</span></strong>。这一变化Ҏ来说真是有点怸着头脑了,我不清楚<strong><span lang="EN-US">#pragma once</span></strong>的工作方式是如何的。而我现在遇到的问题又与这个有兟뀂找扄上的内容看吧。上<span lang="EN-US">google</span>搜了半天Q那些论坛里的回{基本上都是“防止重复包?strong>头文?/strong>的,你不用管他。”这L。可是不他真的行吗Q我刚学?span lang="EN-US">VC++</span>Q我看的书上是没有讲q这个内容的。怎么在网上也搜不到呢Q经q我不懈的努力,l于让我扑ֈ了一?span lang="EN-US"><a ><font color="#009933">http://www.yesky.com/127/1736627_3.shtml</font></a></span>?span lang="EN-US"><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN-BOTTOM: 15.6pt; TEXT-INDENT: 24pt"> <span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">作?span lang="EN-US">Adding</span>的这D话Ҏ的帮助最大:?/span> <span style="FONT-SIZE: 12pt; FONT-FAMILY: 楷体_GB2312">既然使用了包含文ӞZ么还要在<span lang="EN-US">class CMainFrame</span>前添?span lang="EN-US">"<strong>class CViewerView;</strong>"</span>{代码?如果用包含文件代替它Q行不行Q  很多<span lang="EN-US">Visual C++</span>书籍对这些问题避而不谈,但实际上q是一个重要的问题。如果不能理解上qC码,我们很可能ؓ无法通过~译而大伤脑{。这些问题的出现是基于这L一些事实:在我们用标准<span lang="EN-US">C/C++</span>设计E序Ӟ有一个原则即两个代码文g不能怺包含Q而且多次包含q会造成重复定义的错误。ؓ了解册个难题,<span lang="EN-US"> Visual C++</span>使用<span lang="EN-US">#pragma once</span>来通知~译器在生成时只包含<span lang="EN-US">(</span>打开<span lang="EN-US">)</span>一ơ,也就是说Q在W一?span lang="EN-US">#include</span>之后Q编译器重新生成时不会再对这些包含文件进行包?span lang="EN-US">(</span>打开<span lang="EN-US">)</span>和读取,因此我们看到在用向导创徏的所有类的头文g中有<strong><span lang="EN-US">#pragma once</span></strong>语句׃会觉得奇怪了。然?span style="COLOR: red">正是׃q个语句而造成了在W二?span lang="EN-US">#include</span>后编译器无法正确识别所引用的类。因此,我们在相互包含时q需要加入类?span lang="EN-US">class CViewerView</span>q样的语句来通知~译器这个类是一个实际的调用?/span></span> <span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">?span lang="EN-US"><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN-BOTTOM: 15.6pt; TEXT-INDENT: 24pt"> <span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">看来是q个问题了。把我的代码一加上那些cȝ声明以后果然通过了编译。我感觉q个问题?span lang="EN-US">VC++</span>里面来说应该是值得注意的。可能是׃我刚?span lang="EN-US">VC++</span>Q见识太的原故吧。无论如何先C来,说不定也有h在ؓq个<strong><span lang="EN-US">#pragma once</span></strong>伤脑{呢?span lang="EN-US"><o:p></o:p></span></span> </p> </div> </div> <img src ="http://www.shnenglu.com/yuanyajie/aggbug/16445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2006-12-14 18:16 <a href="http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16445.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>烦h的类型{?/title><link>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16429.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Thu, 14 Dec 2006 06:22:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16429.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/16429.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16429.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/16429.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/16429.html</trackback:ping><description><![CDATA[ <h4 class="TextColor1" id="subjcns!F1593BEB77A25884!108" style="MARGIN-BOTTOM: 0px">Ҏx据类型{换的整理</h4> <div class="33r399p" id="msgcns!F1593BEB77A25884!108"> <div> <p>int i = 100;<br />long l = 2001;<br />float f=300.2;<br />double d=12345.119;<br />char username[]="E佩?;<br />char temp[200];<br />char *buf;<br />CString str;<br />_variant_t v1;<br />_bstr_t v2;<br /><br /><font color="#6699ff"><b>一、其它数据类型{换ؓ字符?/b></font><br /></p> <ul> <li> <font color="#6699ff">短整?int)</font> <br />itoa(i,temp,10);///i转换为字W串攑օtemp?最后一个数字表C十q制<br />itoa(i,temp,2); ///按二q制方式转换 </li> <li> <font color="#6699ff">长整?long)</font> <br />ltoa(l,temp,10); </li> <li> <font color="#6699ff">点?float,double)</font> <br />用fcvt可以完成转换,q是MSDN中的例子:<br />int decimal, sign; <br />char *buffer; <br />double source = 3.1415926535; <br />buffer = _fcvt( source, 7, &decimal, &sign ); <br />q行l果:source: 3.1415926535 buffer: '31415927' decimal: 1 sign: 0<br />decimal表示数点的位置,sign表示W号:0为正敎ͼ1? </li> <li> <font color="#6699ff">CString变量</font> <br />str = "2008北京奥运";<br />buf = (LPSTR)(LPCTSTR)str; </li> <li> <font color="#6699ff">BSTR变量</font> <br />BSTR bstrValue = ::SysAllocString(L"E序?); <br />char * buf = _com_util::ConvertBSTRToString(bstrValue); <br />SysFreeString(bstrValue); <br />AfxMessageBox(buf); <br />delete(buf); </li> <li> <font color="#6699ff">CComBSTR变量</font> <br />CComBSTR bstrVar("test"); <br />char *buf = _com_util::ConvertBSTRToString(bstrVar.m_str); <br />AfxMessageBox(buf); <br />delete(buf); <br /></li> <li> <font color="#6699ff">_bstr_t变量</font> <br />_bstr_tcd是对BSTR的封装,因ؓ已经重蝲?操作W,所以很Ҏ使用<br />_bstr_t bstrVar("test"); <br />const char *buf = bstrVar;///不要修改buf中的内容 <br />AfxMessageBox(buf); <br /><br /></li> <li> <font color="#6699ff">通用Ҏ(针对非COM数据cd)</font> <br />用sprintf完成转换<br /><pre>char buffer[200]; char c = '1'; int i = 35; long j = 1000; float f = 1.7320534f; sprintf( buffer, "%c",c); sprintf( buffer, "%d",i); sprintf( buffer, "%d",j); sprintf( buffer, "%f",f); </pre></li> </ul> <p> <b> <font color="#6699ff">二、字W串转换为其它数据类?/font> </b> <br />strcpy(temp,"123"); </p> <ul> <li> <font color="#6699ff">短整?int)</font> <br />i = atoi(temp); </li> <li> <font color="#6699ff">长整?long)</font> <br />l = atol(temp); </li> <li> <font color="#6699ff">点(double)</font> <br />d = atof(temp); </li> <li> <font color="#6699ff">CString变量</font> <br />CString name = temp; </li> <li> <font color="#6699ff">BSTR变量</font> <br />BSTR bstrValue = ::SysAllocString(L"E序?); <br />...///完成对bstrValue的?br />SysFreeString(bstrValue); <br /></li> <li> <font color="#6699ff">CComBSTR变量</font> <br />CComBSTRcd变量可以直接赋?br />CComBSTR bstrVar1("test");<br />CComBSTR bstrVar2(temp);<br /></li> <li> <font color="#6699ff">_bstr_t变量</font> <br />_bstr_tcd的变量可以直接赋?br />_bstr_t bstrVar1("test"); <br />_bstr_t bstrVar2(temp); <br /><br /></li> </ul> <p> <b> <font color="#6699ff">三、其它数据类型{换到CString</font> </b> <br />使用CString的成员函数Format来{?例如:<br /></p> <ul> <li>整数(int)<br />str.Format("%d",i); </li> <li>点?float)<br />str.Format("%f",i); </li> <li>字符串指?char *){已l被CString构造函数支持的数据cd可以直接赋?br />str = username; </li> <li>对于Format所不支持的数据cdQ可以通过上面所说的关于其它数据cd转化到char *的方法先转到char *Q然后赋值给CString变量?br /></li> </ul> <p> <b> <font color="#6699ff">四、BSTR、_bstr_t与CComBSTR</font> </b> <br /> </p> <ul> <li>CComBSTR 是ATL对BSTR的封装,_bstr_t是C++对BSTR的封?BSTR?2位指?但ƈ不直接指向字串的~冲区?br />char *转换到BSTR可以q样: <br />BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上comutil.h和comsupp.lib<br />SysFreeString(bstrValue); <br />反之可以使用<br />char *p=_com_util::ConvertBSTRToString(b);<br />delete p;<br />具体可以参考一Q二D落里的具体说明?br /><br />CComBSTR与_bstr_t对大量的操作W进行了重蝲Q可以直接进?,!=,=={操作,所以用非常方ѝ?br />特别是_bstr_t,大家使用它?br /></li> </ul> <p> <b> <font color="#6699ff">五、VARIANT 、_variant_t ?COleVariant</font> </b> <br /> </p> <ul> <li>VARIANT的结构可以参考头文gVC98\Include\OAIDL.H中关于结构体tagVARIANT的定义?br />对于VARIANT变量的赋|首先lvt成员赋|指明数据cdQ再对联合结构中相同数据cd的变量赋|举个例子Q?br />VARIANT va;<br />int a=2001;<br />va.vt=VT_I4;///指明整型数据<br />va.lVal=a; ///赋? </li> <li> </li> <li> </li> <li>_variant_t是VARIANT的封装类Q其赋值可以用强制类型{换,其构造函C自动处理q些数据cd?br />使用旉加上#include <comdef.h><br />例如Q?br />long l=222;<br />ing i=100;<br />_variant_t lVal(l);<br />lVal = (long)i; </li> <li> <br />COleVariant的用与_variant_t的方法基本一P请参考如下例子:<br />COleVariant v3 = "字符?, v4 = (long)1999;<br />CString str =(BSTR)v3.pbstrVal;<br />long i = v4.lVal;<br /><br />////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// </li> <li> <p>本主题演C如何将各种 C++ 字符串类型{换ؓ其他字符丌Ӏ可以{换的字符串类型包?<strong>char *</strong>?strong>wchar_t*</strong>?a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl03',this);" ><font color="#000080">_bstr_t</font></a>?a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl04',this);" ><font color="#000080">CComBSTR</font></a>?a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl05',this);" ><font color="#000080">CString</font></a>?a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl06',this);" ><font color="#000080">basic_string</font></a> ?<a onclick="javascript:TrackThisClick('ctl00_LibFrame_ctl02','ctl00_LibFrame_ctl07',this);" ><font color="#000080">System.String</font></a>。在所有情况下Q在字W串转换为新cdӞ都会创徏字符串的副本。对新字W串q行的Q何更攚w不会影响原始字符Ԍ反之亦然?/p> <h1 class="heading">?char * 转换</h1> <div id="xxjx3vl" class="seeAlsoNoToggleSection" id="sectionSection0"> </div> <h1 class="heading">CZ</h1> <div id="fjh9rt3" class="seeAlsoNoToggleSection" id="sectionSection1"> <h3 class="subHeading">说明</h3> <div id="l3bh3jb" class="subSection"> <p>此示例演C如何从 <strong>char *</strong> 转换Z面列出的其他字符串类型?/p> </div> <div id="ntvtftp" class="subSection"> <div id="3nzdh9x" class="code" id="ctl00_LibFrame_ctl08_other"> <div id="hxbtxlb" class="CodeSnippetTitleBar"> <div id="j9l1r3b" class="CodeDisplayLanguage"> </div> </div> <pre class="code" id="ctl00_LibFrame_ctl08other" space="preserve">// convert_from_char.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { char *orig = "Hello, World!"; cout << orig << " (char *)" << endl; // Convert to a wchar_t* size_t origsize = strlen(orig) + 1; const size_t newsize = 100; size_t convertedChars = 0; wchar_t wcstring[newsize]; mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring(orig); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string string basicstring(orig); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }</pre> </div> </div> <h3 class="subHeading">输出</h3> <div id="3d99xhx" class="subSection"> <pre>Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (basic_string) Hello, World! (System::String)</pre> </div> </div> <h1 class="heading">?wchar_t * 转换</h1> <div id="xvxrlzp" class="seeAlsoNoToggleSection" id="sectionSection2"> </div> <h1 class="heading">CZ</h1> <div id="b39jl9t" class="seeAlsoNoToggleSection" id="sectionSection3"> <h3 class="subHeading">说明</h3> <div id="dln9b9b" class="subSection"> <p>此示例演C如何从 <strong>wchar_t *</strong> 转换Z面列出的其他字符串类型?/p> </div> <div id="ljf3b93" class="subSection"> <div id="zxblxvt" class="code" id="ctl00_LibFrame_ctl09_other"> <div id="pfzbv3f" class="CodeSnippetTitleBar"> <div id="zpjdpvt" class="CodeDisplayLanguage"> </div> </div> <pre class="code" id="ctl00_LibFrame_ctl09other" space="preserve">// convert_from_wchar_t.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { wchar_t *orig = L"Hello, World!"; wcout << orig << L" (wchar_t *)" << endl; // Convert to a char* size_t origsize = wcslen(orig) + 1; const size_t newsize = 100; size_t convertedChars = 0; char nstring[newsize]; wcstombs_s(&convertedChars, nstring, origsize, orig, _TRUNCATE); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring(orig); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string wstring basicstring(orig); basicstring += L" (basic_string)"; wcout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }</pre> </div> </div> <h3 class="subHeading">输出</h3> <div id="h33p9nt" class="subSection"> <pre>Hello, World! (wchar_t *) Hello, World! (char *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (basic_string) Hello, World! (System::String)</pre> </div> </div> <h1 class="heading">?_bstr_t 转换</h1> <div id="n9lht9j" class="seeAlsoNoToggleSection" id="sectionSection4"> </div> <h1 class="heading">CZ</h1> <div id="9x3rt9v" class="seeAlsoNoToggleSection" id="sectionSection5"> <h3 class="subHeading">说明</h3> <div id="bpjdvt3" class="subSection"> <p>此示例演C如何从 <strong>_bstr_t</strong> 转换Z面列出的其他字符串类型?/p> </div> <div id="p9v9jbr" class="subSection"> <div id="3vh3zlj" class="code" id="ctl00_LibFrame_ctl10_other"> <div id="lz3f9b3" class="CodeSnippetTitleBar"> <div id="l399h9h" class="CodeDisplayLanguage"> </div> </div> <pre class="code" id="ctl00_LibFrame_ctl10other" space="preserve">// convert_from_bstr_t.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { _bstr_t orig("Hello, World!"); wcout << orig << " (_bstr_t)" << endl; // Convert to a char* const size_t newsize = 100; char nstring[newsize]; strcpy_s(nstring, (char *)orig); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* wchar_t wcstring[newsize]; wcscpy_s(wcstring, (wchar_t *)orig); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a CComBSTR CComBSTR ccombstr((char *)orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring((char *)orig); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string string basicstring((char *)orig); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String((char *)orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }</pre> </div> </div> <h3 class="subHeading">输出</h3> <div id="xlxrj3d" class="subSection"> <pre>Hello, World! (_bstr_t) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (basic_string) Hello, World! (System::String)</pre> </div> </div> <h1 class="heading">?CComBSTR 转换</h1> <div id="lztnzfv" class="seeAlsoNoToggleSection" id="sectionSection6"> </div> <h1 class="heading">CZ</h1> <div id="l3b1j9n" class="seeAlsoNoToggleSection" id="sectionSection7"> <h3 class="subHeading">说明</h3> <div id="z3fr3zv" class="subSection"> <p>此示例演C如何从 <strong>CComBSTR</strong> 转换Z面列出的其他字符串类型?/p> </div> <div id="pd99r1p" class="subSection"> <div id="znhjlbh" class="code" id="ctl00_LibFrame_ctl11_other"> <div id="dlf33x9" class="CodeSnippetTitleBar"> <div id="jrlfx3j" class="CodeDisplayLanguage"> </div> </div> <pre class="code" id="ctl00_LibFrame_ctl11other" space="preserve">// convert_from_ccombstr.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" #include "vcclr.h" using namespace std; using namespace System; using namespace System::Runtime::InteropServices; int main() { CComBSTR orig("Hello, World!"); CW2A printstr(orig); cout << printstr << " (CComBSTR)" << endl; // Convert to a char* const size_t newsize = 100; char nstring[newsize]; CW2A tmpstr1(orig); strcpy_s(nstring, tmpstr1); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* wchar_t wcstring[newsize]; wcscpy_s(wcstring, orig); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CString CString cstring(orig); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string wstring basicstring(orig); basicstring += L" (basic_string)"; wcout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }</pre> </div> </div> <h3 class="subHeading">输出</h3> <div id="fv9j39l" class="subSection"> <pre>Hello, World! (CComBSTR) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CString) Hello, World! (basic_string) Hello, World! (System::String)</pre> </div> </div> <h1 class="heading">?CString 转换</h1> <div id="3l3fr9r" class="seeAlsoNoToggleSection" id="sectionSection8"> </div> <h1 class="heading">CZ</h1> <div id="v33j9xd" class="seeAlsoNoToggleSection" id="sectionSection9"> <h3 class="subHeading">说明</h3> <div id="xlxp339" class="subSection"> <p>此示例演C如何从 <strong>CString</strong> 转换Z面列出的其他字符串类型?/p> </div> <div id="9dxj3nd" class="subSection"> <div id="3x3rd9d" class="code" id="ctl00_LibFrame_ctl12_other"> <div id="hv93b9h" class="CodeSnippetTitleBar"> <div id="dlfxbhx" class="CodeDisplayLanguage"> </div> </div> <pre class="code" id="ctl00_LibFrame_ctl12other" space="preserve">// convert_from_cstring.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { CString orig("Hello, World!"); wcout << orig << " (CString)" << endl; // Convert to a char* const size_t newsize = 100; char nstring[newsize]; strcpy_s(nstring, orig); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* // You must first convert to a char * for this to work. size_t origsize = strlen(orig) + 1; size_t convertedChars = 0; wchar_t wcstring[newsize]; mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(orig); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a basic_string string basicstring(orig); basicstring += " (basic_string)"; cout << basicstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }</pre> </div> </div> <h3 class="subHeading">输出</h3> <div id="3vxp3f9" class="subSection"> <pre>Hello, World! (CString) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (basic_string) Hello, World! (System::String)</pre> </div> </div> <h1 class="heading">?basic_string 转换</h1> <div id="v33jt39" class="seeAlsoNoToggleSection" id="sectionSection10"> </div> <h1 class="heading">CZ</h1> <div id="9zjfznl" class="seeAlsoNoToggleSection" id="sectionSection11"> <h3 class="subHeading">说明</h3> <div id="vdf3vf3" class="subSection"> <p>此示例演C如何从 <strong>basic_string</strong> 转换Z面列出的其他字符串类型?/p> </div> <div id="rztlp9h" class="subSection"> <div id="brlfrpn" class="code" id="ctl00_LibFrame_ctl13_other"> <div id="bht9h9v" class="CodeSnippetTitleBar"> <div id="3jvxj33" class="CodeDisplayLanguage"> </div> </div> <pre class="code" id="ctl00_LibFrame_ctl13other" space="preserve">// convert_from_basic_string.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" using namespace std; using namespace System; int main() { string orig("Hello, World!"); cout << orig << " (basic_string)" << endl; // Convert to a char* const size_t newsize = 100; char nstring[newsize]; strcpy_s(nstring, orig.c_str()); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* // You must first convert to a char * for this to work. size_t origsize = strlen(orig.c_str()) + 1; size_t convertedChars = 0; wchar_t wcstring[newsize]; mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(orig.c_str()); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(orig.c_str()); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring(orig.c_str()); cstring += " (CString)"; cout << cstring << endl; // Convert to a System::String String ^systemstring = gcnew String(orig.c_str()); systemstring += " (System::String)"; Console::WriteLine("{0}", systemstring); delete systemstring; }</pre> </div> </div> <h3 class="subHeading">输出</h3> <div id="bp9d3b9" class="subSection"> <pre>Hello, World! (basic_string) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (System::String)</pre> </div> </div> <h1 class="heading">?System::String 转换</h1> <div id="nb9pbrx" class="seeAlsoNoToggleSection" id="sectionSection12"> </div> <h1 class="heading">CZ</h1> <div id="b3z9399" class="seeAlsoNoToggleSection" id="sectionSection13"> <h3 class="subHeading">说明</h3> <div id="339t999" class="subSection"> <p>此示例演C如何从 <strong>System.String</strong> 转换Z面列出的其他字符串类型?/p> </div> <div id="3zlfxf9" class="subSection"> <div id="vdxpt99" class="code" id="ctl00_LibFrame_ctl14_other"> <div id="h3frv39" class="CodeSnippetTitleBar"> <div id="rztnp9t" class="CodeDisplayLanguage"> </div> </div> <pre class="code" id="ctl00_LibFrame_ctl14other" space="preserve">// convert_from_system_string.cpp // compile with /clr /link comsuppw.lib #include <iostream> #include <stdlib.h> #include <string> #include "atlbase.h" #include "atlstr.h" #include "comutil.h" #include "vcclr.h" using namespace std; using namespace System; using namespace System::Runtime::InteropServices; int main() { String ^orig = gcnew String("Hello, World!"); Console::WriteLine("{0} (System::String)", orig); pin_ptr<const wchar_t> wch = PtrToStringChars(orig); // Convert to a char* size_t origsize = wcslen(wch) + 1; const size_t newsize = 100; size_t convertedChars = 0; char nstring[newsize]; wcstombs_s(&convertedChars, nstring, origsize, wch, _TRUNCATE); strcat_s(nstring, " (char *)"); cout << nstring << endl; // Convert to a wchar_t* wchar_t wcstring[newsize]; wcscpy_s(wcstring, wch); wcscat_s(wcstring, L" (wchar_t *)"); wcout << wcstring << endl; // Convert to a _bstr_t _bstr_t bstrt(wch); bstrt += " (_bstr_t)"; cout << bstrt << endl; // Convert to a CComBSTR CComBSTR ccombstr(wch); if (ccombstr.Append(L" (CComBSTR)") == S_OK) { CW2A printstr(ccombstr); cout << printstr << endl; } // Convert to a CString CString cstring(wch); cstring += " (CString)"; cout << cstring << endl; // Convert to a basic_string wstring basicstring(wch); basicstring += L" (basic_string)"; wcout << basicstring << endl; delete orig; }</pre> </div> </div> <h3 class="subHeading">输出</h3> <div id="339lxpn" class="subSection"> <pre>Hello, World! (System::String) Hello, World! (char *) Hello, World! (wchar_t *) Hello, World! (_bstr_t) Hello, World! (CComBSTR) Hello, World! (CString) Hello, World! (basic_string)</pre> </div> </div> </li> </ul> </div> </div> <img src ="http://www.shnenglu.com/yuanyajie/aggbug/16429.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2006-12-14 14:22 <a href="http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16429.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CString和string的互相{?/title><link>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16427.html</link><dc:creator>清源游民</dc:creator><author>清源游民</author><pubDate>Thu, 14 Dec 2006 06:11:00 GMT</pubDate><guid>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16427.html</guid><wfw:comment>http://www.shnenglu.com/yuanyajie/comments/16427.html</wfw:comment><comments>http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16427.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/yuanyajie/comments/commentRss/16427.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/yuanyajie/services/trackbacks/16427.html</trackback:ping><description><![CDATA[ <h4 class="TextColor1" id="subjcns!944d768f73c602d6!193" style="MARGIN-BOTTOM: 0px"> </h4> <div class="33n9ld9" id="msgcns!944d768f73c602d6!193"> <div>CString->std::string 例子Q?br /><br />CString strMfc=“test?<br /><br />std::string strStl;<br /><br />strStl=strMfc.GetBuffer(0);<br /><br />std::string->CString  例子Q?br /><br />CString strMfcQ?br /><br />std::string strStl=“test?<br /><br />strMfc=strStl.c_str(); </div> </div> <img src ="http://www.shnenglu.com/yuanyajie/aggbug/16427.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/yuanyajie/" target="_blank">清源游民</a> 2006-12-14 14:11 <a href="http://www.shnenglu.com/yuanyajie/archive/2006/12/14/16427.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.svelan.cn" target="_blank">AVþ</a>| <a href="http://www.cyjeans.com.cn" target="_blank">99þһ</a>| <a href="http://www.bqb2.cn" target="_blank">þۺ88</a>| <a href="http://www.huiju58.cn" target="_blank">þúݺɫۺ</a>| <a href="http://www.kftfk.cn" target="_blank">Ʒþþþþ</a>| <a href="http://www.taobaomaiba.cn" target="_blank">޾Ʒþþþþο</a>| <a href="http://www.9n7.com.cn" target="_blank">˺ݺۺϾþ</a>| <a href="http://www.zjjhart.cn" target="_blank">ùƷӰ˾þ</a>| <a href="http://www.t421.cn" target="_blank">Ʒþþþþþ</a>| <a href="http://www.iaro.cn" target="_blank">þùAV䡪ٶ</a>| <a href="http://www.25552l.cn" target="_blank">Բľþþþþ</a>| <a href="http://www.stwyy.cn" target="_blank">þþŷղAV</a>| <a href="http://www.122v.cn" target="_blank">ŷƷһþ˵</a>| <a href="http://www.bassaphoto.cn" target="_blank">þþAVҰ</a>| <a href="http://www.dishengbao.cn" target="_blank">ɫݺȷӰþ</a>| <a href="http://www.d4ycf2r.cn" target="_blank">ݺɫɫݺݺۺϾþ</a>| <a href="http://www.swangxinwen.cn" target="_blank">aëƬ÷˾þ</a>| <a href="http://www.itkuo.cn" target="_blank">þˬˬAV</a>| <a href="http://www.chuchu8.cn" target="_blank">˾Ʒþۺ </a>| <a href="http://www.ltbhs.com.cn" target="_blank">˾ƷþѶ</a>| <a href="http://www.yixue114.cn" target="_blank">ھƷþþþþþþ</a>| <a href="http://www.mpyx.net.cn" target="_blank">þþƷר</a>| <a href="http://www.bfnzt.cn" target="_blank">AVһþ</a>| <a href="http://www.hkrczp.cn" target="_blank">þ</a>| <a href="http://www.jiademandu.cn" target="_blank">Ʒ18þþ⺾</a>| <a href="http://www.zhunsan.cn" target="_blank">ھƷþ</a>| <a href="http://www.ahyjj.cn" target="_blank">þҹҹݺ2022</a>| <a href="http://www.better-led.cn" target="_blank">ݺ޾þþþþۺ</a>| <a href="http://www.6ht.com.cn" target="_blank">Ʒһþ㽶߿</a>| <a href="http://www.shangtoo.cn" target="_blank">뾫Ʒþþɫ</a>| <a href="http://www.pbbu.cn" target="_blank">þۺɫݺ</a>| <a href="http://www.hthotel.com.cn" target="_blank">þۺϹɫ88þþƷۺ </a>| <a href="http://www.b8800.cn" target="_blank">ɫʹþۺ</a>| <a href="http://www.t5573.cn" target="_blank">þü¶</a>| <a href="http://www.qxmobile.cn" target="_blank">99þþƷһѿ</a>| <a href="http://www.baaag.cn" target="_blank">ƷƵþ</a>| <a href="http://www.hbrsksy.cn" target="_blank">þþþƷѹĻ</a>| <a href="http://www.sjz10086.cn" target="_blank">69þҹɫƷ69</a>| <a href="http://www.dbwlcom.cn" target="_blank">þþƷ99͵ </a>| <a href="http://www.b5ezt1.cn" target="_blank">þþƷһ</a>| <a href="http://www.yue88.cn" target="_blank">ھƷþþþþþcoent </a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>