??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美成a人片免费看久久,亚洲国产精品久久久久网站,欧美日韩精品久久免费http://www.shnenglu.com/colys/category/3604.htmlLIFE AS CODEzh-cnTue, 20 May 2008 19:07:25 GMTTue, 20 May 2008 19:07:25 GMT60插花问题的“动态规划法”算法[转]http://www.shnenglu.com/colys/articles/33753.htmlcolyscolysMon, 08 Oct 2007 05:40:00 GMThttp://www.shnenglu.com/colys/articles/33753.htmlhttp://www.shnenglu.com/colys/comments/33753.htmlhttp://www.shnenglu.com/colys/articles/33753.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/33753.htmlhttp://www.shnenglu.com/colys/services/trackbacks/33753.html/*
 作者:成晓?br> 旉Q?001q?0?1?11:35:38-12:35:00)
 内容Q完成插花问题的“动态规划法”法及注?br>*/
#include "stdafx.h"
#include "string.h"
#define MAX(A,B) ((A) > (B) ? (A):(B))
//--------------------鲜花问题--------------------
#define F 100
#define V 100
/*
 插花问题描述:
   f束鲜花插入v个花瓶中,使达到最徍的视觉效果,
  问题相关U定及插p?
   鲜花被编号ؓ1--f,q被编号ؓ1--v,q按从到
  大顺序排?一只花瓶只能插一支花,鲜花i插入qj中的
  视觉效果效果值已?~号的鲜花所攑օ的花瓶编号也?nbsp;
 问题求解思\:
   qj(1<=j<=v)中插入鲜q可能~号为[1..j](~号
  的鲜花所攑օ的花瓶编号也?;
   设数lp[i][j]表示鲜花i插入qj的好看程?数组
  q[i][j]表示[1..i]束鲜花插入[1..j]个花瓶所能得到的最?br>  好看E度,初始化q[0][0] = 0;q[0][j]=0(1<=j<=v),则q[f][v]
  是问题的?
   特别?j束鲜花插入到前面的j只花瓶中,所得到的好?br>  E度是q[j][j] = p[1][1]+p[2][2]+...+[j][j].现将插花q?br>  E按q排列序划分成不同阶D?则在Wj阶段,Wi束鲜?br>  若放入第j可?最大好看程度是q[i-1][j-1]+p[i][j];Wi束鲜
  p攑օ前j-1个花瓶中的某一?所得的好看E度是q[i][j-1],
  那么在第j阶段,插入Wi束鲜花所能得到的最大好看程度ؓ:
  q[i][j] = MAX(q[i-1][j-1]+p[i][j],q[i][j-1]),要q[i][j]
  最?应q[i-1][j-1]和q[i][j-1]也最?br>*/
//初始化函?br>void Initialize(int *f,int *v,int p[][V])
{
 int i,j;
 printf("输入鲜花数量及花瓶个?");
 scanf("%d%d",f,v);
 printf("序输入各鲜花插入各q的好看程?\n");
 for(i=1;i<=*f;i++)
  for(j=1;j<=*v;j++)
   p[i][j] = i+j;
   //scanf("%d",&p[i][j]);
}
//鲜花问题处理函数
int Sove(int p[][V],int f,int v,int *way)
{
 int i,j,newv,q[F][V];
 q[0][0] = 0;
 /*讄v个花瓶分别被插入v束鲜花时各号q对应?初始)最大好看程?/
 for(j=1;j<=v;j++)
 {
  q[0][j] = 0;
  /*讄Wj束鲜花放入第j可瓶中的最大好看程?/
  q[j][j] = q[j-1][j-1]+p[j][j];
 }
 for(j=1;j<=v;j++)
  for(i=1;i<j;i++)
   q[i][j] = MAX(q[i-1][j-1]+p[i][j],q[i][j-1]);
 newv = v;
 for(i=f;i>0;i--)
 {
  while(q[i-1][newv-1]+p[i][newv] < q[i][newv])
   newv--;
  //定鲜花i插在qnewv?q准备考虑前一只花瓶 
  way[i] = newv--;
 }
 return(q[f][v]);
}
//--------------------鲜花问题--------------------
//--------------------最长子串问?-------------------
#define N 100
char a[N],b[N],str[N];
//计算两个序列最长公共子序列的长?br>int Get_LongSubStr_Len(char *a,char *b,int c[][N])
{
 int m=strlen(a),n=strlen(b),//两个序列的长?br>  i,j;//循环变量
 for(i=0;i<=m;i++) c[i][0] = 0;
 for(i=1;i<=n;i++) c[0][i] = 0;
 for(i=1;i<=m;i++)
  for(j=1;j<=n;j++)
   if(a[i-1]==b[j-1])
    c[i][j] = c[i-1][j-1]+1;
   else
    c[i][j] = MAX(c[i-1][j],c[i][j-1]);
   /*
    if(c[i-1][j]>=c[i][j-1])
     c[i][j] = c[i-1][j];
    else
     c[i][j] = c[i][j-1];
     */
 return(c[m][n]);
}
//构造最长公共子序列
char *Build_LongSubStr(char s[],char *a,char *b)
{
 int i=strlen(a),j=strlen(b),
  k,c[N][N];
 k = Get_LongSubStr_Len(a,b,c);
 s[k] = '\0';
 while(k>0)
 {
  if(c[i][j]==c[i-1][j])
   i--;
  else
  {
   if(c[i][j]==c[i][j-1])
    j--;
   else
   {
    s[--k]=a[i-1];
    i--;
    j--;
   }
  }
 }
 return(s);
}
//--------------------最长子串问?-------------------
int main(int argc, char* argv[])
{
 int i,f,v,p[F][V],way[F];
 //-----------------------------------
 /*
 Initialize(&f,&v,p);
 printf("最大好看程度ؓ%d\n",Sove(p,f,v,way));
 printf("插有鲜花的花瓶是:\n");
 for(i=1;i<=f;i++)
  printf("%4d",way[i]);
 */
 //-----------------------------------
 printf("输入两个字符?长度<%d):\n",N);
 scanf("%s%s",a,b);
 printf("两个串的最长公共子序列?%s\n",Build_LongSubStr(str,a,b));
 //-----------------------------------
 printf("\n\n应用E序正在q行......\n");
 return 0;
}


colys 2007-10-08 13:40 发表评论
]]>
[转]ini文gUC++d代码http://www.shnenglu.com/colys/articles/28387.htmlcolyscolysThu, 19 Jul 2007 14:21:00 GMThttp://www.shnenglu.com/colys/articles/28387.htmlhttp://www.shnenglu.com/colys/comments/28387.htmlhttp://www.shnenglu.com/colys/articles/28387.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/28387.htmlhttp://www.shnenglu.com/colys/services/trackbacks/28387.html阅读全文

colys 2007-07-19 22:21 发表评论
]]>
成员函数指针与高性能的C++委托(?http://www.shnenglu.com/colys/articles/25793.htmlcolyscolysThu, 07 Jun 2007 16:18:00 GMThttp://www.shnenglu.com/colys/articles/25793.htmlhttp://www.shnenglu.com/colys/comments/25793.htmlhttp://www.shnenglu.com/colys/articles/25793.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/25793.htmlhttp://www.shnenglu.com/colys/services/trackbacks/25793.html  
  和成员函数指针不同,你不隑֏现委托的用处。最重要的,使用委托可以很容易地实现一?Subject/Observer设计模式的改q版[GoF, p. 293]。ObserverQ观察者)模式昄在GUI中有很多的应用,但我发现它对应用E序核心的设计也有很大的作用。委托也可用来实现策略(StrategyQ[GoF, p. 315]和状态(StateQ[GoF, p. 305]模式?br>  
  现在Q我来说明一个事实,委托和成员函数指针相比ƈ不仅仅是好用Q而且比成员函数指针简单得多!既然所有的.NET语言都实C委托Q你可能会猜惛_此高层的概念在汇~代码中q不好实现。但事实q不是这P委托的实现确实是一个底层的概念Q而且像普通的函数调用一L单(q且很高效)。一个C++委托只需要包含一个this 指针和一个简单的函数指针够了。当你徏立一个委托时Q你提供q个委托一个this指针Qƈ向它指明需要调用哪一个函数。编译器可以在徏立委托时计算整this指针需要的偏移量。这样在使用委托的时候,~译器就什么事情都不用做了。这一Ҏ好的是,~译器可以在~译时就可以完成全部q些工作Q这L话,委托的处理对~译器来说可以说是微不道的工作了。在x86pȝ下将委托处理成的汇编代码应该是q么单:
  
  mov ecx, [this]
  
  call [pfunc]
  
  但是Q在标准C++中却不能生成如此高效的代码?BorlandZ解决委托的问题在它的C++~译器中加入了一个新的关键字Q__closureQ?用来通过z的语法生成优化的代码。GNU~译器也对语aq行了扩展,但和Borland的编译器不兼宏V如果你使用了这两种语言扩展中的一U,你就会限制自己只使用一个厂家的~译器。而如果你仍然遵@标准C++的规则,你仍然可以实现委托,但实现的委托׃会是那么高效了?br>  
  有趣的是Q在C#和其?NET语言中,执行一个委托的旉要比一个函数调用慢8倍(参见http://msdn.microsoft.com/library/en- us/dndotnet/html/fastmanagedcode.aspQ。我猜测q可能是垃圾攉?NET安全查的需要。最q,微Y?#8220;l一事g模型Qunified event modelQ?#8221;加入到Visual C++中,随着q个模型的加入,增加了__event?__raise、__hook、__unhook、event_source和event_receiver{一些关键字。坦白地_我对加入的这些特性很反感Q因是完全不W合标准的,q些语法是丑陋的Q因为它们ɘq种C++不像C++Qƈ且会生成一堆执行效率极低的代码?br>  
  解决q个问题的推动力Q对高效委托Qfast delegateQ的q切需?br>  
  使用标准C++实现委托有一个过度臃肿的症状。大多数的实现方法用的是同一U思\。这些方法的基本观点是将成员函数指针看成委托K�但这L指针只能被一个单独的cM用。ؓ了避免这U局限,你需要间接地使用另一U思\Q你可以使用模版为每一个类建立一?#8220;成员函数调用器(member function invokerQ?#8221;。委托包含了this指针和一个指向调用器QinvokerQ的指针Qƈ且需要在堆上为成员函数调用器分配I间?br>  
  对于q种Ҏ已经有很多种实现Q包括在CodeProject上的实现Ҏ。各U实现在复杂性上、语法(比如Q有的和C#的语法很接近Q上、一般性上有所不同。最h威的一个实现是boost::function。最q,它已l被采用作ؓ下一个发布的C++标准版本中的一部分[Sutter1]。希望它能够被广泛地使用?br>  
  像传统的委托实现方法一P我同样发觉这U方法ƈ不十分另人满意。虽然它提供了大家所期望的功能,但是会؜淆一个潜在的问题Qh们缺乏对一个语a的底层的构造?“成员函数调用?#8221;的代码对几乎所有的c都是一LQ在所有^C都出现这U情冉|令h沮的。毕竟,堆被用上了。但在一些应用场合下Q这U新的方法仍然无法被接受?br>  
  我做的一个项目是L事g模拟器,它的核心是一个事件调度程序,用来调用被模拟的对象的成员函数。大多数成员函数非常单:它们只改变对象的内部状态,有时在事仉列(event queueQ中d来要发生的事gQ在q种情况下最适合使用委托。但是,每一个委托只被调用(invokedQ一ơ。一开始,我用了boost:: functionQ但我发现程序运行时Q给委托所分配的内存空间占用了整个E序I间的三分之一q要多!“我要真正的委托!”我在内心呼喊着Q?#8220;真正的委托只需要仅仅两行汇~指令啊Q?#8221;
  
  我ƈ不能L能够得到我想要的Q但后来我很q运。我在这儿展C的代码Q代码下载链接见译者注Q几乎在所有编译环境中都生了优化的汇~代码。最重要的是Q调用一个含有单个目标的委托Qsingle-target delegateQ的速度几乎同调用一个普通函C样快。实现这L代码q没有用C么高q东西Q唯一的遗憑ְ是,Z实现目标Q我的代码和标准C++ 的规则有些偏R我使用了一些有x员函数指针的未公开知识才它能够这样工作。如果你很细心,而且不在意在数情况下的一些编译器相关Qcompiler-specificQ的代码Q那么高性能的委托机制在MC++~译器下都是可行的?br>  
  诀H:Q何类型的成员函数指针转化Z个标准的形式
  
  我的代码的核心是一个能够将Mcȝ指针和Q何成员函数指针分别{换ؓ一个通用cȝ指针和一个通用成员函数的指针的cR由于C++没有“通用成员函数Qgeneic member functionQ?#8221;的类型,所以我把所有类型的成员函数都{化ؓ一个在代码中未定义的CGenericClasscȝ成员函数?br>  
  大多数编译器Ҏ有的成员函数指针q等地对待,不管他们属于哪个cR所以对q些~译器来_可以使用reinterpret_cast一个特定的成员函数指针转化Z个通用成员函数指针。事实上Q假如编译器不可以,那么q个~译器是不符合标准的。对于一些接q标准(almost-compliantQ的~译器,比如Digital MarsQ成员函数指针的reinterpret_cast转换一般会涉及C些额外的Ҏ代码Q当q行转化的成员函数的cM间没有Q何关联时Q编译器会出错。对q些~译器,我们使用一个名为horrible_cast的内联函敎ͼ在函C使用了一个union来避免C++的类型检查)。用这U方法看来是不可避免的�Kboost::function也用Cq种Ҏ?br>  
  对于其他的一些编译器Q如Visual C++, Intel C++和Borland C++Q,我们必须多重(multiple-Q承和虚拟Qvirtual-Q承类的成员函数指针{化ؓ单一Qsingle-Q承类的函数指针。ؓ了实现这个目的,我y妙地使用了模板ƈ利用了一个奇妙的戏法。注意,q个戏法的用是因ؓq些~译器ƈ不是完全W合标准的,但是使用q个戏法得到了回报:它ɘq些~译器生了优化的代码?br>  
  既然我们知道~译器是怎样在内部存储成员函数指针的Qƈ且我们知道在问题中应该怎样为成员函数指针调整this指针Q我们的代码在设|委托时可以自己调整this指针。对单一l承cȝ函数指针Q则不需要进行调_对多重承,则只需要一ơ加法就可完成调_对虚拟?..有些麻烦了。但是这样做是管用的Qƈ且在大多数情况下Q所有的工作都在~译时完成!
  
  q是最后一个诀H。我们怎样区分不同的承类型?q没有官方的Ҏ来让我们区分一个类是多重承的q是其他cd的ѝ但是有一Uy妙的ҎQ你可以查看我在前面l出了一个列表(见中)——对MSVCQ每U承方式生的成员函数指针的大是不同的。所以,我们可以Z成员函数指针的大用模版!比如对多重承类型来_q只是个单的计算。而在定unknown_inheritanceQ?6字节Q类型的时候,也会采用cM的计方法?br>  
  对于微Y和英特尔的编译器中采用不标准12字节的虚拟承类型的指针的情况,我引发了一个编译时错误Qcompile-time errorQ,因ؓ需要一个特定的q行环境QworkaroundQ。如果你在MSVC中用虚拟承,要在声明cM前?FASTDELEGATEDECLARE宏。而这个类必须使用unknown_inheritanceQ未知承类型)指针Q这相当于一个假定的 __unknown_inheritance关键字)。例如:
  
FASTDELEGATEDECLARE(CDerivedClass)
  
  
class CDerivedClass : virtual public CBaseClass1, virtual public CBaseClass2 {
  
  
// : (etc)
  
  };

  
  q个宏和一些常数的声明是在一个隐藏的命名I间中实现的Q这样在其他~译器中使用时也是安全的。MSVCQ?.0或更新版本)的另一U方法是在工E中使用/vmg~译器选项。而Inter的编译器?vmg~译器选项不v作用Q所以你必须在虚拟承类中用宏。我的这个代码是因ؓ~译器的bug才可以正运行,你可以查看代码来了解更多l节。而在遵从标准的编译器中不需要注意这么多Q况且在M情况下都不会妨碍FASTDELEGATEDECLARE宏的使用?br>  
  一旦你类的对象指针和成员函数指针转化为标准Ş式,实现单一目标的委托(single-target delegateQ就比较Ҏ了(虽然做v来感觉冗长乏呻I。你只要为每一U具有不同参数的函数制作相应的模板类p了。实现其他类型的委托的代码也大都与此怼Q只是对参数E做修改|了?br>  
  q种用非标准方式转换实现的委托还有一个好处,是委托对象之间可以用等式比较。目前实现的大多数委托无法做到这一点,qɘq些委托不能胜Q一些特定的dQ比如实现多播委托(multi-cast delegatesQ?[Sutter3]?br>  
  静态函C为委托目标(delegate targetQ?br>  
  理论上,一个简单的非成员函敎ͼnon-member functionQ,或者一个静态成员函敎ͼstatic member functionQ可以被作ؓ委托目标Qdelegate targetQ。这可以通过静态函数{换ؓ一个成员函数来实现。我有两U方法实现这一点,两种Ҏ都是通过使委托指向调用这个静态函数的“调用器(invokerQ?#8221;的成员函数的Ҏ来实现的?br>

colys 2007-06-08 00:18 发表评论
]]>
成员函数指针与高性能的C++委托(?http://www.shnenglu.com/colys/articles/25790.htmlcolyscolysThu, 07 Jun 2007 16:17:00 GMThttp://www.shnenglu.com/colys/articles/25790.htmlhttp://www.shnenglu.com/colys/comments/25790.htmlhttp://www.shnenglu.com/colys/articles/25790.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/25790.htmlhttp://www.shnenglu.com/colys/services/trackbacks/25790.html
引子

标准C++中没有真正的面向对象的函数指针。这一点对C++来说是不q的Q因为面向对象的指针Q也叫做“闭包QclosureQ?#8221;?#8220;委托QdelegateQ?#8221;Q在一些语a中已l证明了它宝늚价倹{在Delphi (Object Pascal)中,面向对象的函数指针是Borland可视化组建库QVCLQVisual Component LibraryQ的基础。而在目前QC#?#8220;委托”的概忉|流行,q也正显C出C#q种语言的成功。在很多应用E序中,“委托”化了松耦合对象的设计模式[GoF]。这U特性无疑在标准C++中也会生很大的作用?br>
很遗憾,C++中没?#8220;委托”Q它只提供了成员函数指针Qmember function pointersQ。很多程序员从没有用q函数指针,q是有特定的原因的。因为函数指针自w有很多奇怪的语法规则Q比?#8220;->*”?#8220;.*”操作W)Q而且很难扑ֈ它们的准含义,q且你会扑ֈ更好的办法以避免使用函数指针。更h讽刺意味的是Q事实上Q编译器的编写者如果实?#8220;委托”的话会比他费劲地实现成员函数指针要容易地多!

在这文章中Q我要揭开成员函数指针?#8220;秘的盖?#8221;。在D地重q成员函数指针的语法和特性之后,我会向读者解释成员函数指针在一些常用的~译器中是怎样实现的,然后我会向大家展C编译器怎样有效地实?#8220;委托”。最后我会利用这些精q知识向你展示在C++~译器上实现优化而可靠的“委托”的技术。比如,在Visual C++(6.0, .NET, and .NET 2003)中对单一目标委托Qsingle-target delegateQ的调用Q编译器仅仅生成两行汇编代码Q?br>
函数指针

下面我们复习一下函数指针。在C和C++语言中,一个命名ؓmy_func_ptr的函数指针指向一个以一个int和一个char*为参数的函数Q这个函数返回一个Q点|声明如下Q?br>
float (*my_func_ptr)(intchar *);


//Z便于理解Q我强烈推荐你用typedef关键字?br>
//如果不这L话,当函数指针作Z个函数的参数传递的时候,

// E序会变得晦涩难懂?br>
// q样的话Q声明应如下所C:

typedef float (*MyFuncPtrType)(intchar *);

MyFuncPtrType my_func_ptr;


应注意,Ҏ一个函数的参数l合Q函数指针的cd应该是不同的。在Microsoft Visual C++Q以下称MSVCQ中Q对三种不同的调用方式有不同的类型:__cdecl, __stdcall, 和__fastcall。如果你的函数指针指向一个型如float some_func(int, char *)的函敎ͼq样做就可以了:
my_func_ptr = some_func;

//当你惌用它所指向的函数时Q你可以q样写:

(
*my_func_ptr)(7"Arbitrary String");


你可以将一U类型的函数指针转换成另一U函数指针类型,但你不可以将一个函数指针指向一个void *型的数据指针。其他的转换操作׃用详叙了。一个函数指针可以被讄?来表明它是一个空指针。所有的比较q算W(==, !=, <, >, <=, >=Q都可以使用Q可以?#8220;==0”或通过一个显式的布尔转换来测试指针是否ؓI(nullQ?br>
在C语言中,函数指针通常用来像qsort一样将函数作ؓ参数Q或者作为Windowspȝ函数的回调函数等{。函数指针还有很多其他的应用。函数指针的实现很简单:它们只是“代码指针Qcode pointerQ?#8221;Q它们体现在汇编语言中是用来保存子程序代码的首地址。而这U函数指针的存在只是Z保证使用了正的调用规范?br>
成员函数指针

在C++E序中,很多函数是成员函敎ͼ卌些函数是某个cM的一部分。你不可以像一个普通的函数指针那样指向一个成员函敎ͼ正确的做法应该是Q你必须使用一个成员函数指针。一个成员函数的指针指向cM的一个成员函敎ͼq和以前有相同的参数Q声明如下:

float (SomeClass::*my_memfunc_ptr)(intchar *);

//对于使用const关键字修饰的成员函数Q声明如下:

float (SomeClass::*my_const_memfunc_ptr)(intchar *const;


注意使用了特D的q算W(::*Q,?#8220;SomeClass”是声明中的一部分。成员函数指针有一个可怕的限制Q它们只能指向一个特定的cM的成员函数。对每一U参数的l合Q需要有不同的成员函数指针类型,而且ҎU用const修饰的函数和不同cM的函敎ͼ也要有不同的函数指针cd。在MSVC中,对下面这四种调用方式都有一U不同的调用cdQ__cdecl, __stdcall, __fastcall, ?__thiscall。(__thiscall是缺省的方式Q有的是,在Q何官Ҏ档中从没有对__thiscall关键字的详细描述Q但是它l常在错误信息中出现。如果你昑ּC用它Q你会看?#8220;它被保留作ؓ以后使用Qit is reserved for future useQ?#8221;的错误提C。)如果你用了成员函数指针Q你最好用typedef以防止؜淆?br>
函数指针指向型如float SomeClass::some_member_func(int, char *)的函敎ͼ你可以这样写Q?br>
my_memfunc_ptr = &SomeClass::some_member_func;


很多~译器(比如MSVCQ会让你L“&”Q而其他一些编译器Q比如GNU G++Q则需要添?#8220;&”Q所以在手写E序的时候我把它M。若要调用成员函数指针,你需要先建立SomeClass的一个实例,q用特D操作符“->*”Q这个操作符的优先较低Q你需要将光当地放入圆括号内?br>
SomeClass *= new SomeClass;

(x
->*my_memfunc_ptr)(6"Another Arbitrary Parameter");

//如果cd栈上Q你也可以?#8220;.*”q算W?/span>

SomeClass y;

(y.
*my_memfunc_ptr)(15"Different parameters this time");


不要怪我使用如此奇怪的语法——看hC++的设计者对标点W号有着p的感情!C++相对于C增加了三U特D运符来支持成员指针?#8220;::*”用于指针的声明,?#8220;->*”?#8220;.*”用来调用指针指向的函数。这Lh对一个语a模糊而又很少使用的部分的q分x是多余的。(你当然可以重?#8220;->*”q些q算W,但这不是本文所要涉及的范围。)

一个成员函数指针可以被讄?Qƈ可以使用“==”?#8220;!=”比较q算W,但只能限定在同一个类中的成员函数的指针之间进行这L比较。Q何成员函数指针都可以?做比较以判断它是否ؓI。与函数指针不同Q不{运符Q?lt;, >, <=, >=Q对成员函数指针是不可用的?br>
成员函数指针的怪异之处

成员函数指针有时表现得很奇怪。首先,你不可以用一个成员函数指针指向一个静态成员函敎ͼ你必M用普通的函数指针才行Q在q里“成员函数指针”会生误解,它实际上应该?#8220;非静态成员函数指?#8221;才对Q。其ơ,当用类的承时Q会出现一些比较奇怪的情况。比如,下面的代码在MSVC下会~译成功Q注意代码注释)Q?br>
Qi nclude “stdio.h”

class SomeClass {

public:

virtual void some_member_func(int x, char *p) {

printf(
"In SomeClass"); };

};

class DerivedClass : public SomeClass {

public:

// 如果你把下一行的注释销掉,带有 line (*)的那一行会出现错误

// virtual void some_member_func(int x, char *p) { printf("In DerivedClass"); };

};

int main() {

//声明SomeClass的成员函数指?/span>

typedef 
void (SomeClass::*SomeClassMFP)(intchar *);

SomeClassMFP my_memfunc_ptr;

my_memfunc_ptr 
= &DerivedClass::some_member_func; // ---- line (*)

return 0;

}


奇怪的是,&DerivedClass::some_member_func是一个SomeClasscȝ成员函数指针Q而不是DerivedClasscȝ成员函数指针Q(一些编译器E微有些不同Q比如,对于Digital Mars C++Q在上面的例子中Q?amp;DerivedClass::some_member_func会被认ؓ没有定义。)但是Q如果在DerivedClasscM重写QoverrideQ了some_member_func函数Q代码就无法通过~译Q因为现在的&DerivedClass::some_member_func已成为DerivedClasscM的成员函数指针!

成员函数指针之间的类型{换是一个讨v来非常模p的话题。在C++的标准化的过E中Q在涉及l承的类的成员函数指针时Q对于将成员函数指针转化为基cȝ成员函数指针q是转化为子cL员函数指针的问题和是否可以将一个类的成员函数指针{化ؓ另一个不相关的类的成员函数指针的问题Qh们曾有过很激烈的争论。然而不q的是,在标准委员会做出军_之前Q不同的~译器生产商已经Ҏ自己对这些问题的不同的回{实C自己的编译器。根据标准(W?.2.10/9节)Q你可以使用reinterpret_cast在一个成员函数指针中保存一个与本来的类不相关的cȝ成员函数。有x员函数指针{换的问题的最l结果也没有定下来。你现在所能做的还是像以前那样——将成员函数指针转化为本cȝ成员函数的指针。在文章的后面我会l讨个问题,因ؓq正是各个编译器对这样一个标准没有达成共识的一个话题?br>
在一些编译器中,在基cd子类的成员函数指针之间的转换时常有怪事发生。当涉及到多重承时Q用reinterpret_cast子c{换成基类ӞҎ一特定~译器来说有可能通过~译Q而也有可能通不q编译,q取决于在子cȝ基类列表中的基类的顺序!下面是一个例子:

class Derived: public Base1, public Base2 // 情况 (a)

class Derived2: public Base2, public Base1 // 情况 (b)

typedef 
void (Derived::* Derived_mfp)();

typedef 
void (Derived2::* Derived2_mfp)();

typedef 
void (Base1::* Base1mfp) ();

typedef 
void (Base2::* Base2mfp) ();

Derived_mfp x;


对于情况(a)Qstatic_cast<Base1mfp> (x) 是合法的Q而static_cast<Base2mfp> (x) 则是错误的。然而情?b)却与之相反。你只可以安全地子cȝ成员函数指针转化为第一个基cȝ成员函数指针Q如果你要实验一下,MSVC会发出C4407可告,而Digital Mars C++会出现编译错误。如果用reinterpret_cast代替static_castQ这两个~译器都会发生错误,但是两种~译器对此有着不同的原因。但是一些编译器Ҏl节|之不理Q大家可要小心了Q?br>
标准C++中另一条有的规则是:你可以在cd义之前声明它的成员函数指针。这对一些编译器会有一些无法预料的副作用。我待会讨论q个问题Q现在你只要知道要尽可能得避免这U情况就是了?br>
需要值得注意的是Q就像成员函数指针,标准C++中同h供了成员数据指针Qmember data pointerQ。它们具有相同的操作W,而且有一些实现原则也是相同的。它们用在stl::stable_sort的一些实现方案中Q而对此很多其他的应用我就不再提及了?br>
成员函数指针的?br>
现在你可能会觉得成员函数指针是有些奇异。但它可以用来做什么呢Q对此我在网上做了非常广泛的调查。最后我ȝZ用成员函数指针的两点原因Q?br>
    * 用来做例子给
    * C++初学者看Q帮助它们学习语法;或?Z实现“委托Q?br>      delegateQ?#8221;Q?

成员函数指针在STL和Boost库的单行函数适配器(one-line function adaptorQ中的用是微不道的,而且允许你将成员函数和标准算法؜合用。但是它们最重要的应用是在不同类型的应用E序框架中,比如它们形成了MFC消息pȝ的核心?br>
当你使用MFC的消息映宏Q比如ON_COMMANDQ时Q你会组装一个包含消息ID和成员函数指针(型如QCCmdTarget::*成员函数指针Q的序列。这是MFCcdȝ承CCmdTarget才可以处理消息的原因之一。但是,各种不同的消息处理函数具有不同的参数列表Q比如OnDraw处理函数的第一个参数的cd为CDC *Q,所以序列中必须包含各种不同cd的成员函数指针。MFC是怎样做到q一点的呢?MFC利用了一个可怕的~译器漏z(hackQ,它将所有可能出现的成员函数指针攑ֈ一个庞大的联合QunionQ中Q从而避免了通常需要进行的C++cd匚w查。(看一下afximpl.h和cmdtarg.cpp中名为MessageMapFunctions的unionQ你׃发现q一恐怖的事实。)因ؓMFC有如此重要的一部分代码Q所以事实是Q所有的~译器都个漏z开了绿灯。(但是Q在后面我们会看刎ͼ如果一些类用到了多重承,q个漏洞在MSVC中就不会起作用,q正是在使用MFC时只能必M用单一l承的原因。)

在boost::function中有cM的漏z(但不是太严重Q。看h如果你想做Q何有x员函数指针的比较有趣的事Q你必d好与q个语言的漏z进行挑战的准备。要是你惛_定C++的成员函数指针设计有~陷的观点,看来是很隄?br>
在写q篇文章中,我有一炚w要指明:“允许成员函数指针之间q行转换QcastQ,而不允许在{换完成后调用其中的函?#8221;Q把q个规则U_C++的标准中是可W的。首先,很多行的编译器对这U{换不支持Q所以,转换是标准要求的Q但不是可移植的Q。其ơ,所有的~译器,如果转换成功Q调用{换后的成员函数指针时仍然可以实现你预期的功能Q那~译器就没有所谓的“undefined behaviorQ未定义的行为)”q类错误出现的必要了Q调用(InvocationQ是可行的,但这不是标准Q)。第三,允许转换而不允许调用是完全没有用处的Q只有{换和调用都可行,才能方便而有效地实现委托Q从而ɘq种语言受益?br>
Z让你信q一h争议的论断,考虑一下在一个文件中只有下面的一D代码,q段代码是合法的Q?br>
class SomeClass;

typedef 
void (SomeClass::* SomeClassFunction)(void);

void Invoke(SomeClass *pClass, SomeClassFunction funcptr)
{
      (pClass
->*funcptr)();
};


注意到编译器必须生成汇编代码来调用成员函数指针,其实~译器对SomeClasscM无所知。显Ӟ除非链接器进行了一些极端精l的优化措施Q否则代码会忽视cȝ实际定义而能够正地q行。而这造成的直接后果是Q你可以“安全?#8221;调用从完全不同的其他cM转换q来的成员函数指针?br>
释我的断a的另一半——{ 换ƈ不能按照标准所说的方式q行Q我需要在l节上讨论编译器是怎样实现成员函数指针的。我同时会解释ؓ什么用成员函数指针的规则h如此严格的限制。获 得详l论q成员函数指针的文不是太容易,q且大家寚w误的a论已l习以ؓ怺Q所以,我仔l检查了一pd~译器生成的汇编代码……



colys 2007-06-08 00:17 发表评论
]]>
C++成员函数指针的应?/title><link>http://www.shnenglu.com/colys/articles/25785.html</link><dc:creator>colys</dc:creator><author>colys</author><pubDate>Thu, 07 Jun 2007 15:33:00 GMT</pubDate><guid>http://www.shnenglu.com/colys/articles/25785.html</guid><wfw:comment>http://www.shnenglu.com/colys/comments/25785.html</wfw:comment><comments>http://www.shnenglu.com/colys/articles/25785.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/colys/comments/commentRss/25785.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/colys/services/trackbacks/25785.html</trackback:ping><description><![CDATA[<font size="3"> C++中,成员指针是最为复杂的语法l构。但在事仉动和多线E应用中被广泛用于调用回叫函数。在多线E应用中Q每个线E都通过指向成员函数的指针来调用该函数。在q样的应用中Q如果不用成员指针,~程是非常困隄?<br><br>  刚遇到这U语法时也许会让你止步不前。但你会发现Q用恰当的cd定义之后Q复杂的语法是可以简化的。本文引g了解成员函数指针的声明,赋值和调用回叫函数?<br><br>  <strong>成员函数指针的声?/strong> <br><br>  一个成员函数指针包括成员函数的q回cdQ后?:操作W类名,指针名和函数的参数。初看上去,语法有点复杂。其实可以把它理解ؓ一个指向原函数的指针,格式是:函数q回cdQ类名,::操作W,指针星号Q指针名Q函数参数?<br><br>  一个指向外部函数的指针声明为: <br><br>  void (*pf)(char *, const char *); <br><br>  void strcpy(char * dest, const char * source); <br><br>  pf=strcpy; <br><br>  一个指向类A成员函数的指针声明ؓQ?<br><br>  void (A::*pmf)(char *, const char *); <br><br>  声明的解释是Qpmf是一个指向A成员函数的指针,q回无类型|函数带有二个参数Q参数的cd分别是char * ?const char *。除了在星号前增加A:: Q与声明外部函数指针的方法一栗?<br><br>  <strong>赋?/strong> <br><br>  l成员指针赋值的Ҏ是将函数名通过指针W号&赋予指针名。如下所C: <br><br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;"><font>class</font></span><span style="color: #000000;"><font> A<br>{<br><br>  </font></span><span style="color: #0000ff;"><font>public</font></span><span style="color: #000000;"><font>:<br><br>   </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> strcpy(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>);<br><br>   </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> strcat(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>);<br><br>};<br>pmf </font></span><span style="color: #000000;"><font>=</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>&</font></span><span style="color: #000000;"><font>A::strcpy; </font></span></div> <br><br>  有些老的~译器可以通过没有&L赋值方式,但标准C++强制要求加上&受?<br><br>  <strong>使用cd定义</strong> <br><br>  可以用类型定义来隐藏复杂的成员指针语法。例如,下面的语句定义了PMA是一个指向A成员函数的指针,函数q回无类型|函数参数cd为char * ?const char *Q?<br><br>  typedef void(A::*PMA)(char *, const char *); <br><br>  PMA pmf= &A::strcat; // pmf是PMFcd(cA成员指针)的变?<br><br>  下文会看C用类型定义特别有利于声明成员指针数组?<br><br>  <strong>通过成员指针调用成员函数</strong> <br><br> 可以在不必知道函数名的情况下Q通过成员指针调用对象的成员函数。例如,函数dispatcher有一个变量pmfQ通过它调用类成员函数Q不它调用 的是strcpy()函数q是strcat()函数。指向外部原函数的指针和指向cL员函数的指针是有很大区别的。后者必L向被调函数的宿主对象。因 此,除了要有成员指针外,q要有合法对象或对象指针?<br><br>  CD例做q一步说明。假设A有二个实例,成员函数指针支持多态性。这样在成员指针调用虚成员函数时是动态处理的(x谓后联编 - 译注)。注意,不可调用构造和析构函数。示例如下: <br><br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;"><font>    A a1, a2;<br><br>  A </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>p</font></span><span style="color: #000000;"><font>=</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>&</font></span><span style="color: #000000;"><font>a1; </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>创徏指向A的指?br><br>  </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>创徏指向成员的指针ƈ初始?/font></span><span style="color: #008000;"><font><br></font></span><span style="color: #000000;"><font><br>  </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> (A::</font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>pmf)(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>) </font></span><span style="color: #000000;"><font>=</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>&</font></span><span style="color: #000000;"><font>A::strcpy;<br><br>  </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>要将成员函数l定到pmfQ必d义呼叫的对象?br><br>  </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>可以?号引|</font></span><span style="color: #008000;"><font><br></font></span><span style="color: #000000;"><font><br>  </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> dispatcher(A a, </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> (A::</font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>pmf)(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>))<br><br>  {<br><br>   </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> str[</font></span><span style="color: #000000;"><font>4</font></span><span style="color: #000000;"><font>];<br><br>   (a.</font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>pmf)(str, “abc”); </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>成员函数绑定到pmf</font></span><span style="color: #008000;"><font><br></font></span><span style="color: #000000;"><font><br>  }<br><br>  </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>或用A的指针表达方式指向成员指针:</font></span><span style="color: #008000;"><font><br></font></span><span style="color: #000000;"><font><br>  </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> dispatcher(A </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font> p, </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> (A::</font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>pmf)(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>))<br><br>  {<br><br>   </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> str[</font></span><span style="color: #000000;"><font>4</font></span><span style="color: #000000;"><font>]; (p</font></span><span style="color: #000000;"><font>->*</font></span><span style="color: #000000;"><font>pmf)(str, “abc”);<br><br>  }<br><br>  </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>函数的调用方法ؓQ?/font></span><span style="color: #008000;"><font><br></font></span><span style="color: #000000;"><font><br>  dispatcher(a, pmf); </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font> .* 方式</font></span><span style="color: #008000;"><font><br></font></span><span style="color: #000000;"><font><br>  dispatcher(</font></span><span style="color: #000000;"><font>&</font></span><span style="color: #000000;"><font>a, pmf); </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font> ->* 方式 </font></span></div> <br>高使用技?<br><br>  以上是成员函数的基本知识。现在介l它的高U用技巧?<br><br>  <strong>成员指针数组</strong> <br><br>  在下例,声明了一个含有二个成员指针的数组Qƈ分配cȝ成员函数地址l成员指针: <br><br>  PMA pmf[2]= {&A::strcpy, &A::strcat}; <br>也就?br>      void (A::*PMA[2])(char *, const char *)= {&A::strcpy, &A::strcat}; <br><br>  q样的数l在菜单驱动应用中很有用。选择菜单后Q应用将调用相应的回叫函敎ͼ如下所C: <br><br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;"><font>    enum</font></span><span style="color: #000000;"><font> MENU_OPTIONS { COPY, CONCAT };<br><br>  </font></span><span style="color: #0000ff;"><font>int</font></span><span style="color: #000000;"><font> main()<br>  {<br>   MENU_OPTIONS option; </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> str[</font></span><span style="color: #000000;"><font>4</font></span><span style="color: #000000;"><font>];<br>   </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>从外部资源读取选项</font></span><span style="color: #008000;"></span><span style="color: #000000;"><font><br>   </font></span><span style="color: #0000ff;"><font>switch</font></span><span style="color: #000000;"><font> (option)<br>   {<br>    </font></span><span style="color: #0000ff;"><font>case</font></span><span style="color: #000000;"><font> COPY:<br><br>     (pa</font></span><span style="color: #000000;"><font>->*</font></span><span style="color: #000000;"><font>pmf[COPY])(str, “abc”);<br><br>     </font></span><span style="color: #0000ff;"><font>break</font></span><span style="color: #000000;"><font>;<br><br>    </font></span><span style="color: #0000ff;"><font>case</font></span><span style="color: #000000;"><font> CONCAT:<br><br>     (pa</font></span><span style="color: #000000;"><font>->*</font></span><span style="color: #000000;"><font>pmf[CONCAT])(str, “abc”);<br><br>     </font></span><span style="color: #0000ff;"><font>break</font></span><span style="color: #000000;"><font>;<br><br>     </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>…</font></span><span style="color: #008000;"><font><br></font></span><span style="color: #000000;"><font><br>   }<br>  } </font></span></div> <br><br>  <strong>Const cd的成员函?/strong> <br><br>  成员指针的类型应该与成员函数cd一致。上面例子中的pmf 可以指向A的Q意函敎ͼ只要该函C是constcd。如下所C,如果touppercase()的地址分配lpmfQ将D~译出错Q因为touppercase() 的类型是const?<br><br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;"><font>   Class A<br>  {<br><br>  </font></span><span style="color: #0000ff;"><font> public</font></span><span style="color: #000000;"><font>:<br><br>     </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> strpcy(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>);<br><br>   </font></span><span style="color: #0000ff;"><font>  void</font></span><span style="color: #000000;"><font> strcat(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>);<br><br>   </font></span><span style="color: #0000ff;"><font>  void</font></span><span style="color: #000000;"><font> touppercase(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>) </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font>;<br><br>  };<br><br>  pmf</font></span><span style="color: #000000;"><font>=&</font></span><span style="color: #000000;"><font>A::touppercase; </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>出错Q类型不匚w<br><br>  </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font>解决的方法是声明一个constcd的成员指针:</font></span><span style="color: #008000;"><font><br></font></span><span style="color: #000000;"><font><br>  </font></span><span style="color: #0000ff;"><font>void</font></span><span style="color: #000000;"><font> (A::pcmf)(</font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>, </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font> </font></span><span style="color: #0000ff;"><font>char</font></span><span style="color: #000000;"><font> </font></span><span style="color: #000000;"><font>*</font></span><span style="color: #000000;"><font>) </font></span><span style="color: #0000ff;"><font>const</font></span><span style="color: #000000;"><font>;<br><br>  pcmf</font></span><span style="color: #000000;"><font>=&</font></span><span style="color: #000000;"><font>A::touppercase; </font></span><span style="color: #008000;"><font>//</font></span><span style="color: #008000;"><font> 现在可以?nbsp;</font></span></div> <br><br>  有些差劲的编译器允许一个非constcd的成员指针指向constcd的成员函数。这在标准C++是不允许的?</font><img src ="http://www.shnenglu.com/colys/aggbug/25785.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/colys/" target="_blank">colys</a> 2007-06-07 23:33 <a href="http://www.shnenglu.com/colys/articles/25785.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++ typedef 函数指针http://www.shnenglu.com/colys/articles/25381.htmlcolyscolysSun, 03 Jun 2007 07:07:00 GMThttp://www.shnenglu.com/colys/articles/25381.htmlhttp://www.shnenglu.com/colys/comments/25381.htmlhttp://www.shnenglu.com/colys/articles/25381.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/25381.htmlhttp://www.shnenglu.com/colys/services/trackbacks/25381.html函数指针

      一个函数在~译时被分配一个入口地址Q将q个入口地址UCؓ函数的指针,?span lang="EN-US">

      以用一个指针变量指向该函数指针Q然后通过该变量来调用函数?span lang="EN-US">

      有关说明Q?span lang="EN-US">

      1、函数指针的声明格式Q?span lang="EN-US">

        函数q回值类型(Q指针变量名Q(参数cd列表Q?span lang="EN-US">

         或者是Q?span lang="EN-US">

         typedef 函数q回值类型 Q*指针变量名)Q参数类型列表)

            2、一个函数指针只能指向一U类型的函数Q即h相同的返回值和相同的参            

        数的函数

      Q、关于函数指针的加减q算没有意义

       函数指针数组定义Q?span lang="EN-US">

             函数定义Q?span lang="EN-US">

             void fun1(void *p);

             void fun2(void *p);

             void fun3(void *p);

       函数指针数组定义Q?span lang="EN-US">

       void(*fun[3])(void*);//typedef void(*pfun)(void*);pfun fun[3];

       指针赋|

             fun[0] = fun1;

             fun[1] = fun2;

             fun[2] = fun3;

             函数调用Q?span lang="EN-US">

       fun[0](&a);         //int a;

             fun[1](&b);         //int b;

             fun[3](&c);         //int c;

          声明一个指向成员函数的指针

一个指向成员函数的指针包括成员函数的返回类型,?em>::W号的类名称Q函数参数表。虽然这一语法看似复杂Q其实它和普通的指针是一L。指向外部函数的指针可如下声明:

void (*pf)(char *, const char *);
void strcpy(char * dest, const char * source);
pf=strcpy;

相应指向c?span lang="EN-US">A的成员函数的指针如下表示Q?span lang="EN-US">

void (A::*pmf)(char *, const char *);

以上pmf是指向类A的一个成员函数的指针Q传递两个变?em>char *?const char *Q没有返回倹{注意星号前面的A::W号Q这和前面的声明是一致的?span lang="EN-US">

赋?span lang="EN-US">
Zl一个指向成员函数的指针赋|可以采用成员函数名ƈ再其前面加一?span lang="EN-US">&的方?/span>
使用typedef

你可以?span lang="EN-US">typedef来隐藏一些指向成员函数的复杂指针。例如,下面的代码定义了一个类A中的成员函数的指?em>PMAQƈ传?em>char *?em>const char *参数?span lang="EN-US">

typedef void(A::*PMA)(char *, const char *);
PMA pmf= &A::strcat; // use a typedef to define a pointer to member

使用typedef特别有用Q尤其是对于指向成员函数的数l指针?span lang="EN-US">

?/font>       voidcd的指?span lang="EN-US">

void含义Q?span lang="EN-US">

void?#8220;无类?#8221;Q?span lang="EN-US">void*则ؓ无类型指针,void*可以指向Mcd的数据?span lang="EN-US">

void aQ?span lang="EN-US">//此变量没有Q何实际意义,无法~译通过“illegal use of type

void 的作用:

     1、对E序q回的限?span lang="EN-US">

     2、对函数参数的限?span lang="EN-US">

我们知道Q如何指?span lang="EN-US">p1?span lang="EN-US">p2的类型相同,那么我们可以直接?span lang="EN-US">p1?span lang="EN-US">p2间赋|如果不同Q必M用强制类型{换?span lang="EN-US">

如:float *p1;   int *p2;

若:p1 = p2; ~译出错Q?#8220;can not covert from int* to float*

必须为:p1 = (float*)p2;

            ?span lang="EN-US">void*不同QQ何类型的指针都可以直接赋为它Q不需要强制类型{换:

            如:void *p1;   int *p2;

                可作Q?span lang="EN-US">p1 =p2;

                无类型可以包ҎcdQ有cd不能包容无类型:

                必须为:p2 = (int*)p1;

            viod ?span lang="EN-US"> void*使用规则ȝQ?span lang="EN-US">

?/font>     如果函数没有q回|那么应声明ؓvoidcd

?/span>C语言中,凡不加返回值类型限定的函数Q就会被~译器作回整型值处理。但是许多程序员却误以ؓ其ؓvoidcd. 林锐博士《高质量C/C++~程》中提到Q?/span>“C++语言有很严格的类型安全检查,不允怸q情况(指函C加类型声明)发生。可是编译器q不一定这么认定,譬如?/span>Visual C++6.0中上q?/span>add函数的编译无错也无警告且q行正确Q所以不能寄希望于编译器会做严格的类型检查?/span>

因此Qؓ了避免؜乱,我们在编?/span>C/C++E序Ӟ对于M函数都必M个不漏地指定其类型。如果函数没有返回|一定要声明?/span>voidcd。这既是E序良好可读性的需要,也是~程规范性的要求。另外,加上voidcd声明后,也可以发挥代码的自注?/span>作用。代码的自注?/span>即代码能自己注释自己?/span>

             ?/span> 如果函数无参敎ͼ那么应声明其参数?/span>void

             ?/span> 心使用void指针cd

                按照ANSI的标准,不能?/span>void指针q行法操作Q即下列操作是不合法的:

                void *pvoid;

                pvoid ++;         //ansi错误

                pvoid += 1;        //ansi 错误

                ansi标准之所以这栯定,是因为它坚持Q进行算法操作的指针必须是确定知道其指向数据cd的大的?/span>

                ?/span>GUNQ?/span>GUNs  Not  UnixQ则不这么认为,它指?/span>void*的算法操作与char*一致。因此在GUN~译器中上述语句是正的?/span>

                在实际的E序中,Zq合ansi标准Qƈ提高E序的可UL性,我们可以q样实现同样功能的代码:

                void *pvoid;

                (char*)pvoid++;

                (char*)pvoid += 1;

             ?如果函数的参数可以是Lcd指针Q那么应声明其参Cؓvoid *

                典型的如内存操作函数memcpy?/span>memset的函数原型分别ؓQ?/span>

                void* memcpy(void *dest, const void *src, size_t len);

                void* memset(void *buffer,int c, size_t num);

                q样QQ何类型的指针都可以传?/span>memcpy?/span>memset中,q也真实CC内存操作函数的意义,因ؓ它操作的对象仅仅是一片内存,而不论内存是什cd?/span>

             ?void不能代表一个真实的变量

                void a; //错误

                function(void a); //错误

?/font>       this指针

《深入浅?span lang="EN-US">MFC》中解释Q?span lang="EN-US">

 定义c?span lang="EN-US">CRectQ定义两个对?span lang="EN-US">rect1?span lang="EN-US">rect2Q各有自qm_color成员变量Q但rect1.setcolor?span lang="EN-US">rect2.setcolor却都是通往唯一?span lang="EN-US">CRect::setcolor成员函数Q那?span lang="EN-US">CRect::setcolor如何处理不同对象?span lang="EN-US">m_colorQ答案是׃个隐藏参敎ͼ名ؓthis指针。当你调用:

rect1.setcolro(2);

rect2.setcolor(3);

Ӟ~译器实际上Z做出来一下的代码Q?span lang="EN-US">

CRect::setcolor(2,(CRect*)&rect1);

CRect::setcolor(3,(CRect*)&rect2);

多出来的参数Q就是所谓的this指针?span lang="EN-US">

class CRect

{

……

public:

  void setcolor(int color){m_color = color};

};

被编译后Q其实ؓQ?span lang="EN-US">

class CRect

{

……

public:

  void setcolor(int color,(CRect*)this){this->m_color = color};

};



colys 2007-06-03 15:07 发表评论
]]>
Ҏ路径创徏不规则窗?/title><link>http://www.shnenglu.com/colys/articles/24791.html</link><dc:creator>colys</dc:creator><author>colys</author><pubDate>Thu, 24 May 2007 15:08:00 GMT</pubDate><guid>http://www.shnenglu.com/colys/articles/24791.html</guid><wfw:comment>http://www.shnenglu.com/colys/comments/24791.html</wfw:comment><comments>http://www.shnenglu.com/colys/articles/24791.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/colys/comments/commentRss/24791.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/colys/services/trackbacks/24791.html</trackback:ping><description><![CDATA[<p> //Ҏ路径创徏不规则窗?br> CDC* pDC;</p> <p> pDC = this->GetDC();<br> ::BeginPath(pDC->m_hDC);<br> <br> //讄为透明模式 <br> ::SetBkMode(pDC->m_hDC, TRANSPARENT);  <br> //<br> RECT rect;<br> this->GetClientRect(&rect);<br> /*三角?br> int TopCenterPoint=rect.left + (rect.right - rect.left) /2;<br> pDC->MoveTo(TopCenterPoint, rect.top);<br> pDC->LineTo(rect.left, rect.bottom - GLOBAL_OVERLEN);<br> pDC->LineTo(rect.right, rect.bottom - GLOBAL_OVERLEN);<br> pDC->LineTo(TopCenterPoint,rect.top);<br> */</p> <p> /*比较奇怪的矩Ş<br> pDC->MoveTo(rect.left, rect.top);<br> pDC->LineTo(rect.right, rect.top);</p> <p> pDC->LineTo(rect.right, rect.bottom - GLOBAL_OVERLEN);</p> <p> pDC->LineTo(rect.left + (rect.right - rect.left) / 2, rect.bottom - GLOBAL_OVERLEN);<br> pDC->LineTo(rect.left + (rect.right - rect.left) / 2, rect.bottom);<br> pDC->LineTo(rect.left + (rect.right - rect.left) / 2 - GLOBAL_OVERWIDTH, rect.bottom - GLOBAL_OVERLEN);</p> <p> pDC->LineTo(rect.left, rect.bottom - GLOBAL_OVERLEN);<br> pDC->LineTo(rect.left, rect.top);<br> */<br> //<br> <br> ::EndPath(pDC->m_hDC);<br> hRgn = ::PathToRegion(pDC->m_hDC);<br> this->SetWindowRgn(hRgn, TRUE);</p><img src ="http://www.shnenglu.com/colys/aggbug/24791.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/colys/" target="_blank">colys</a> 2007-05-24 23:08 <a href="http://www.shnenglu.com/colys/articles/24791.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>d盘文g专题http://www.shnenglu.com/colys/articles/24491.htmlcolyscolysSun, 20 May 2007 15:11:00 GMThttp://www.shnenglu.com/colys/articles/24491.htmlhttp://www.shnenglu.com/colys/comments/24491.htmlhttp://www.shnenglu.com/colys/articles/24491.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/24491.htmlhttp://www.shnenglu.com/colys/services/trackbacks/24491.html?/span>Windowsq_上,d盘文g是相当多应用E序l常会涉及到的一U功能。该主题涉及到采?/span>C/C++/MFC/Win32(API)中提供的接口函数来操作磁盘文件的ҎQ以及其中需要注意的地方?/span>

 

=============================================================

0.      盘文g数据存储方式

在介l各U操作文件方式之前,需要先介绍盘上文件数据的l织方式?/span>

实际上,文g是在计算机内存中以二q制表示的数据在外部存储介质上的另一U存攑Ş式?/span>文g通常分ؓ二进制文件和文本文g?/span>二进制文件是包含?/span>ASCII及扩?/span>ASCII字符中编写的数据或程序指令的文g。一般是可执行文?/span>(Exe)、图形、图像、声音等文g。而文本文?/span>(通常也成?/span>ASCII文g)Q它的每一字节存放的是可表CZؓ一个字W的ASCII代码的文件。这里把文g区分Zq制文g和文本文Ӟ但实际上它们都是以二q制数据的方式来存储的。文本文仉所存储的每一个字节都可以转化Z?/span>可读的字W。譬?/span>a,bQ?/span>但在内存中ƈ不会存储'a', 'b'Q而是存储它们?/span>ASCII码:61?/span>62?/span>

 

1.      C语言Ҏ件操作的支持

?/span>C语言中,对于文g的操作都是利?/span>FILEl构体来q行的。包括文件的打开、文件的d、文件的关闭、文件指针的定位{?/span>

(1)   文g的打开

文g的打开需要用fopen函数。该函数?/span>2个参敎ͼq回gؓ指向之前定义?/span>FILEl构体指针。语法定义ؓ

FILE* fopen(const char* filename, const char* mod);

参数1Q表C打开文g的完整\径,例如: “C:\\Test\\Zero_Test.txt”.

参数2Q打开文g的方式。取gؓ下表所C?/span>

文g打开模式

意义

r/rb

取而打开。如果文件不存在或不能找刎ͼ函数调用p|?/span>

w/wb

为写入而打开一个空文g。如果给定的文g已经存在Q则清空其内宏V?/span>

a/ab

为写入而打开一个文件。如果文件存在,则在文gNd新数据,在写新数据之前不会移除原有的EOF标志。如果文件不存在Q则新徏一个空文g以待写入?/span>

r+/rb+

打开文g用于写入操作和读取操作,文g必须存在?/span>

w+/wb+

为写入操作和d操作打开一个空文g。如果文件已l存在,则清I其内容?/span>

a+/ab+

打开文g用于d操作和添加操作。ƈ且添加操作在d新数据之前会U除该文件中已有?/span>EOF标志Q然后当写入操作完成之后再恢?/span>EOF标志。如果指定文件不存在Q那么首先将新徏一个文件?/span>

在上表中Q没有带b的模式表C打开的是文本文gQ而带b的模式表C打开的是二进制文件?/span>

通常在定义结?/span>FILE时会其初始化ؓNULL。在打开文g函?/span>fopen的返回D值给它。之后需要判断文件是否成功打开Q可采用如下方式Q?/span>

if ((pFile = fopen(“C:\\Test\\Zero_Test.txt”, “w”) == NULL)

   Print(“Opening File Error.”);    // FILE* pFile = NULL;

else

   正常写入数据到文?/span>

 

Q?/span>2Q文件的关闭

在用完一个文件之后应该关闭它Q以防止它再被误用?#8220;关闭”是使文件指针变量不再指向该文gQ其脱钩。函C用方?/span>:

fclose(pFile);

需要注意的?/span>fclose的参数必L有效的文件指针变量,否则q行时会挂掉?/span>

应该L在文件数据操作完成后关闭文g的习惯,如果不关闭文件将会丢失数据。同Ӟ在向文g写数据时Q是现将数据输出到缓冲区Q待~冲区充满后才正式输出给文g。如果程序运行结束而缓冲区q未充满Q则~冲Z的数据将会丢失。因此利用函?/span>fclose来关闭文件可以避免这个问题?/span>

当然Q还有另外一个函?/span>fflushQ也可以用来缓冲区里的数据输出到文件中。函数调用方?/span>:

fflush(pFile);

 

 Q?/span>3Q文件的d

当涉及到大量数据的读写时Q可以采用函?/span>fread?/span>fwrite?/span>q两个函数通常用于二进制文件的d?/span>函数调用方式如下Q?/span>

fread(buffer, size, count, fp);

fwrite(buffer, size, count, fp);

buffer是一个指针,是用来存放数据的变量指针Q例如内|类型变量的指针Q结构体变量指针{?/span>

size是要d的字节数?/span>特别要注意的是,此处q不是数l的大小Q结构体内变量的个数{。最好采?/span>sizeof操作W来求得buffer的内存字节数?/span>

count?/span>size大小的重复次数?/span>

fp是文件指针?/span>

 

对于q样的结构体Q?/span>

typedef struct {

    int clr_sel;             // color mode的选择

    int fixval_sel;          // fixed value的选择

    float thres_val;         // threshold value的确?/span>

    float thres_scrlbar_pos; // threshold scroll bar位置的确?/span>

    int method_sel;          // analysis method的选择

    int usediff_sel;         // use difference of MSA/TSE方式的选择

    int usescat_sel;         // use MSA/TSE of scatter signal 方式的选择

    int remxtalk_sel;        // remove crosstalk 方式的选择

    float timewin_scrlbar_pos; // time window scroll bar位置的确?/span>

    int timewin_sel;         // time window模式的选择

    int freq_sel;            // frequency selection模式的选择

    int path_sel;            // path selection模式的选择  

} IMG_SETTINGS;    

       IMG_SETTINGS m_img_settings;

文gd操作Ӟ可采用如下方式:

fwrite(&m_img_settings, sizeof(m_img_settings), 1, pwFile);

fread(&m_img_settings, sizeof(m_img_settings), 1, prFile);

====================================================

 

如果惌写特定格式的文gQ可采用fprintf?/span>fscanf函数?/span>q两个函数通常是针Ҏ本文件进行操作?/span>

函数调用方式如下Q?/span>

fprintf(pFile, “%d…”, i, j, k …);

fscanf(pFile, “%d…”, i j, k…);

格式化时可以规定d数据的精度,cdQ以及数据之间的分割W等?/span>

例如Q?/span>

fprintf(pFile, " %d %d %d %d %d %d %d %d \n", sigSize, samp_points, samp_rate,40, avrag_num, 0, 0, 0);

fprintf(pFile, "%d %.2f %s %d %d %d %d \n", vpathdef[i].frequency1/1000,

                                   vpathdef[i].amplitude, sig_type.c_str(),     psnset->sensorArray[vpathdef[i].actuator-1].channel-tol,

                     psnset->sensorArray[vpathdef[i].sensor-1].channel-tol,  vpathdef[i].gain, 30);  

特别需要注意的是,如果写入的数据的cd相同Ӟ不可Z便,格式化的字W串写成如此形式(.., ”%d”,i,j,k…); // i,j,k…同整型类型?/span>

如果q样操作的话Q读写的数据便只有数?/span>i了?/span>

 

最后针对一个面试题来对C语言操作文g的方式作一个ȝ.

面试题:l你一个整敎ͼ例如12345Q将q个整数保存到文件中Q要求在以记事本打开该文件时Q显C的?/span>:12345?/span>

l出三种代码Q?/span>

Q?Q?span>    代码1

FILE* pwFile = NULL;

pwFile = fopen(“c:\\Test.txt”, “w”); // create and open file with text mode.

int i = 12345;                       // However, write number with binary mode.

fwrite(&i, 4, 1, pwFile);      // sizeof(int) = 4.

fclose(fwFile);

========================

Q?Q?span>    代码2

FILE* pwFile = NULL;

pwFile = fopen(“c:\\Test.txt”, “w”);

char ch[5] = {1+48, 2+48, 3+48, 4+48, 5+48 };

fwrite(ch, 1, 5, pwFile);      // sizeof(char) = 1, 5*sizeof(char) = 5

fclose(pwFile);

=======================

Q?Q?span>    代码3

FILE* pwFile = NULL;

pwFile = fopen(“c:\\Test.txt”, “w”);

int i = 12345;

char ch[5];

itoa(i, ch, 10);        // transform int number to string

 

fwrite(ch, 1, 5, fwFile);

fclose(pFile);

==============================

Q?Q?span>    代码4

FILE* pwFile = NULL;

pwFile = fopen(“c:\\Test.txt”, “w”);

int i = 12345;

fprintf(pwFile, “%d”, i);   // write number with specified format.

fclose(pwFile);

==============================

 

?/span>4U代码在vc中进行编译运行,可以发现只有方式Q?/span>1Q不满题目要求?br>


to be continued...


colys 2007-05-20 23:11 发表评论
]]>
菜单~程专题http://www.shnenglu.com/colys/articles/24487.htmlcolyscolysSun, 20 May 2007 14:54:00 GMThttp://www.shnenglu.com/colys/articles/24487.htmlhttp://www.shnenglu.com/colys/comments/24487.htmlhttp://www.shnenglu.com/colys/articles/24487.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/24487.htmlhttp://www.shnenglu.com/colys/services/trackbacks/24487.html1.      菜单响应的类序

依次是视cR文类、框架类Q最后才是应用程序类?/span>

 

2.      Windows消息的分c?/span>

实际上,菜单命o也是一U消息。在Windows中,消息分ؓ以下3U:

Q?Q?span>    标准消息

除了WM_COMMAND之外Q所有以WM_开头的消息都是标准消息。从CWndz的类Q都可以接收到该cL息?/span>

Q?Q?span>    命o消息

   来自菜单、加速键或工h按钮的消息。这cL息都是以WM_COMMAND形式呈现。在MFC中,通过菜单的标识(ID)来区分不同的命o消息Q在SDK中,通过消息?/span>wParam参数来标识。从CCmdTargetz的类Q都可以接收到这cL息?/span>

Q?Q?span>    通告消息

   由控件生的消息Q例如按钮的单击、列表框的选择{都会生这cL息,目的是ؓ了向其父H口通知事g的发生。这cL息也是以WM_COMMAND形式呈现的。从CCmdTargetz的类Q都可以接收到这cL息?/span>

׃CWnd是从CCmdTargetz的,故从CWndz的类Q它们既可以接收标准消息Q也可以接收命o消息和通告消息。而对于那些从CCmdTargetz的类Q则只能接收命o消息和通告消息Q不能接收标准消息?/span>

 

3.      菜单命o消息路由的具体过E?/span>

当点L个菜单项Ӟ最先接收到q个菜单命o消息的是框架cR框架类把接收到的q个消息交给它的子窗口,卌c,pc首先进行处理。视c首先根据命令消息映机制查找自w是否对此消息进行了响应Q如果响应了Q就调用响应函数对这个消息进行处理,消息路由q程l束Q如果视cL有对此命令消息做处响应,׃由文类Q文档类同样查找自n是否对这个菜单命令进行了响应Q如果响应了Q就由文档类的命令消息响应函数进行处理,路由q程l束。如果文类也未做出响应Q就把这个命令消息交q给视类Q后者又把该消息交还l框架类。框架类查看自己是否对这个命令消息进行了响应Q如果它也没有作处响应,把q个菜单命o消息交换l应用程序类Q由后者来q行处理?/span>

 

4.      菜单操作

要想获得某个菜单资源Q需使用下面的函数调用:

CMenu* GetMenu() const ;

该函数调用者是CWnd的对象。返回gؓCMenucd象的指针?/span>

通过获得的菜单指针便可以获得其上的某个菜单栏的指针了。调用方式ؓQ?/span>

   CMenu* GetSubMenu(int nPos) const;

调用者是菜单资源的类对象指针Q或者是某个菜单栏的对象指针?/span>

如果某个菜单栏下面还有子菜单,通过可以通过GetSubMenu函数来获得其子菜单项的操作指针。子菜单的索引都是?/span>0开始的Q同时分割栏也是要占据烦引值的?/span>

 

5.      CASEQ?/span>

在资源编辑器中编?/span>Popup Menu资源: IDR_SENSOR_DRAW_MENU?/span>

Grids Style子菜单中的各个选项是相互排斥的。要求选择其中的一个时Q需在其菜单前面标志选择?/span>·Q其它都Zؓ选中。也是?/span>Style中只能选中一个?/span>

可采用两U方式:

Q?/span>1Q映消息:ON_WM_CONTEXTMENU()

void ..::OnContextMenu(CWnd* /*pWnd*/, CPoint point)

Q?/span>2Q映消息:ON_WM_RBUTTONDOWN()

void ..::OnRightBtnDown(.. ..)

响应函数实现代码Q?/span>

{

CMenu menu;

       menu.LoadMenu(IDR_SENSOR_DRAW_MENU); // 装蝲菜单资源

       CMenu* pMenu = menu.GetSubMenu(0);   // 获得Sensor Menu菜单栏的对象指针

       CMenu* pSubMenu = pMenu->GetSubMenu(0); // 获得Grids Style子菜单项的对象指?/span>

       // 以此cLQ如果是Edit Structure字菜单项的对象指针,参数应该?/span>1

       int idxsel = 0;

       switch (m_GridStyle) {

              case GRIDSOFF:

                     idxsel = 0;

                     break;

              case GRIDS10X:

                     idxsel = 2;           // separator is one resource, so take it into account.

                     break;

              case GRIDS20X:

                     idxsel = 3;

                     break;

              case GRIDS30X:

                     idxsel = 4;

                     break;

       }

// Grids Style子菜单项又有N个子菜单,Ҏ索引g|来讄其状态?/span>

       pSubMenu->CheckMenuRadioItem(0, 4, idxsel, MF_BYPOSITION);

// 如果?/span>WM_RBUTTONDOWN响应Q则需要调用函?/span>

ClientToScreen(&point); // 客户坐标{化ؓ屏幕坐标?/span>

// 以下函数的参?/span>x,y是屏q坐标倹{?/span>

       pMenu->TrackPopupMenu(TPM_RIGHTBUTTON,point.x,point.y,this,NULL);

}



colys 2007-05-20 22:54 发表评论
]]>
VC中dll的lib文g和dll有什么不同? http://www.shnenglu.com/colys/articles/24350.htmlcolyscolysFri, 18 May 2007 14:08:00 GMThttp://www.shnenglu.com/colys/articles/24350.htmlhttp://www.shnenglu.com/colys/comments/24350.htmlhttp://www.shnenglu.com/colys/articles/24350.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/24350.htmlhttp://www.shnenglu.com/colys/services/trackbacks/24350.html.lib是在你的E序~译q接的时候就q接的文Ӟ因此你必d知编译器q接的lib文g在那里。一般来_与动态连接文件相ҎQlib文g也被UCؓ是静态连接库。当你把代码~译成这几种格式的文件时Q在以后他们׃可能再被更改?
如果你想使用lib文gQ就必须Q?br>1 包含一个对应的头文件告知编译器lib文g里面的具体内?br>2 讄lib文g允许~译器去查找已经~译好的二进制代?
?果你想从你的代码分离一个dll文g出来代替静态连接库Q仍焉要一个lib文g。这个lib文g被q接到程序告诉操作系l在q行的时候你想用C?dll文gQ一般情况下Qlib文g里有相应的dll文g的名字和一个指明dll输出函数入口的顺序表。如果不想用lib文g或者是没有lib文gQ可?用WIN32 API函数LoadLibrary、GetProcAddress。事实上Q我们可以在Visual C++ IDE中以二进制Ş式打开lib文gQ大多情况下会看到ASCII码格式的C++函数或一些重载操作的函数名字?
一般我们最主要的关于lib文g的麻烦就是出现unresolved symble q类错误Q这是lib文gq接错误或者没有包?c?cpp文g到工E里Q关键是如果在C++工程里用了C语言写的lib文gQ就必需要这样包含:
extern "C"
{
#include "myheader.h"
}
q是因ؓC语言写的lib文g没有C++所必须的名字破坏,C函数不能被重载,因此q接器会出错?img src ="http://www.shnenglu.com/colys/aggbug/24350.html" width = "1" height = "1" />

colys 2007-05-18 22:08 发表评论
]]>
?C 语言~写 Windows 服务E序的五个步?/title><link>http://www.shnenglu.com/colys/articles/24238.html</link><dc:creator>colys</dc:creator><author>colys</author><pubDate>Wed, 16 May 2007 11:56:00 GMT</pubDate><guid>http://www.shnenglu.com/colys/articles/24238.html</guid><wfw:comment>http://www.shnenglu.com/colys/comments/24238.html</wfw:comment><comments>http://www.shnenglu.com/colys/articles/24238.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/colys/comments/commentRss/24238.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/colys/services/trackbacks/24238.html</trackback:ping><description><![CDATA[<table cellSpacing=0 cellPadding=0 width="100%" border=0> <tbody> <tr> <td> <p><strong>Author: Yevgeny Menaker</strong> <br><br><br><a href="http://www.shnenglu.com/Files/colys/memorystatus.rar">下蝲代码</a><br>原文出处Q?a target=_blank>Five Steps to Writing Windows Services in C</a><br><br><strong>摘要</strong><br><br>  Windows 服务被设计用于需要在后台q行的应用程序以及实现没有用户交互的d。ؓ了学习这U控制台应用E序的基知识QCQ不是C++Q是最佳选择。本文将建立q实C个简单的服务E序Q其功能是查询系l中可用物理内存数量Q然后将l果写入一个文本文件。最后,你可以用所学知识编写自q Windows 服务?br>  当初我写W一?NT 服务Ӟ我到 MSDN 上找例子。在那里我找C一?Nigel Thompson 写的文章Q?#8220;<a target=_blank><u><font color=#0000ff>Creating a Simple Win32 Service in C++</font></u></a>”Q这文章附带一?C++ 例子。虽然这文章很好地解释了服务的开发过E,但是Q我仍然感觉~少我需要的重要信息。我想理解通过什么框Ӟ调用什么函敎ͼ以及何时调用Q但 C++ 在这斚w没有让我L多少。面向对象的Ҏ固然方便Q但׃用类对底?Win32 函数调用q行了封装,它不利于学习服务E序的基本知识。这是Z么我觉得 C 更加适合于编写初U服务程序或者实现简单后CQ务的服务。在你对服务E序有了充分透彻的理解之后,?C++ ~写才能游刃有余。当我离开原来的工作岗位,不得不向另一个h转移我的知识的时候,利用我用 C 所写的例子非常容易解?NT 服务之所以然?br>  服务是一个运行在后台q实现勿需用户交互的Q务的控制台程序。Windows NT/2000/XP 操作pȝ提供为服务程序提供专门的支持。h们可以用服务控制面板来配|安装好的服务程序,也就?Windows 2000/XP 控制面板|理工具中的“服务”Q或?#8220;开?#8221;|“q行”对话框中输入 services.msc /s——译者注Q。可以将服务配置成操作系l启动时自动启动Q这样你׃必每ơ再重启pȝ后还要手动启动服务?br>  本文首先解释如何创Z个定期查询可用物理内存ƈ结果写入某个文本文件的服务。然后指g完成生成Q安装和实现服务的整个过E?br><br><br><strong>W一步:d数和全局定义</strong><br><br>首先Q包含所需的头文g。例子要调用 Win32 函数Qwindows.hQ和盘文g写入Qstdio.hQ:</p> <pre>#include <windows.h> #include <stdio.h></pre> <p>接着Q定义两个常量:</p> <pre>#define SLEEP_TIME 5000 #define LOGFILE "C:\\MyServices\\memstatus.txt"</pre> <p>SLEEP_TIME 指定两次q箋查询可用内存之间的毫U间隔。在W二步中~写服务工作循环的时候要使用该常量?br>LOGFILE 定义日志文g的\径,你将会用 WriteToLog 函数内存查询的l果输出到该文gQWriteToLog 函数定义如下Q?/p> <pre>int WriteToLog(char* str) { FILE* log; log = fopen(LOGFILE, "a+"); if (log == NULL) return -1; fprintf(log, "%s\n", str); fclose(log); return 0; }</pre> <p>声明几个全局变量Q以便在E序的多个函C间共享它们倹{此外,做一个函数的前向定义Q?/p> <pre>SERVICE_STATUS ServiceStatus; SERVICE_STATUS_HANDLE hStatus; void ServiceMain(int argc, char** argv); void ControlHandler(DWORD request); int InitService();</pre> <p>  现在Q准备工作已l就l,你可以开始编码了。服务程序控制台E序的一个子集。因此,开始你可以定义一?main 函数Q它是程序的入口炏V对于服务程序来_main 的代码o人惊讶地短,因ؓ它只创徏分派表ƈ启动控制分派机?/p> <pre>void main() { SERVICE_TABLE_ENTRY ServiceTable[2]; ServiceTable[0].lpServiceName = "MemoryStatus"; ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain; ServiceTable[1].lpServiceName = NULL; ServiceTable[1].lpServiceProc = NULL; // 启动服务的控制分z机U程 StartServiceCtrlDispatcher(ServiceTable); }</pre> <p>  一个程序可能包含若q个服务。每一个服务都必须列于专门的分z表中(为此该程序定义了一?ServiceTable l构数组Q。这个表中的每一w要在 SERVICE_TABLE_ENTRY l构之中。它有两个域Q?/p> <ul> <li>lpServiceName: 指向表示服务名称字符串的指针Q当定义了多个服务时Q那么这个域必须指定Q? <li>lpServiceProc: 指向服务d数的指针Q服务入口点Q; </li> </ul> <p>  分派表的最后一必L服务名和服务d数域?NULL 指针Q文本例子程序中只宿M个服务,所以服务名的定义是可选的?br>  服务控制理器(SCMQServices Control ManagerQ是一个管理系l所有服务的q程。当 SCM 启动某个服务Ӟ它等待某个进E的ȝE来调用 StartServiceCtrlDispatcher 函数。将分派表传递给 StartServiceCtrlDispatcher。这把调用q程的主U程转换为控制分z֙。该分派器启动一个新U程Q该U程q行分派表中每个服务?ServiceMain 函数Q本文例子中只有一个服务)分派器还监视E序中所有服务的执行情况。然后分z֙控制请求从 SCM 传给服务?br><br>注意Q如?StartServiceCtrlDispatcher 函数30U没有被调用Q便会报错,Z避免q种情况Q我们必d ServiceMain 函数中(参见本文例子Q或在非d数的单独U程中初始化服务分派表。本文所描述的服务不需要防范这L情况?br><br>  分派表中所有的服务执行完之后(例如Q用户通过“服务”控制面板E序停止它们Q,或者发生错误时。StartServiceCtrlDispatcher 调用q回。然后主q程l止?br><br><br><strong>W二步:ServiceMain 函数</strong><br><br>  <a target=_blank><u><font color=#0000ff>Listing 1</font></u></a> 展示?ServiceMain 的代码。该函数是服务的入口炏V它q行在一个单独的U程当中Q这个线E是由控制分z֙创徏的。ServiceMain 应该可能早早ؓ服务注册控制处理器。这要通过调用 RegisterServiceCtrlHadler 函数来实现。你要将两个参数传递给此函敎ͼ服务名和指向 ControlHandlerfunction 的指针?br>  它指C控制分z֙调用 ControlHandler 函数处理 SCM 控制h。注册完控制处理器之后,获得状态句柄(hStatusQ。通过调用 SetServiceStatus 函数Q用 hStatus ?SCM 报告服务的状态?br><a target=_blank><u><font color=#0000ff>Listing 1</font></u></a> 展示了如何指定服务特征和其当前状态来初始?ServiceStatus l构QServiceStatus l构的每个域都有其用途: <ul> <li>dwServiceTypeQ指C服务类型,创徏 Win32 服务。赋?SERVICE_WIN32Q? <li>dwCurrentStateQ指定服务的当前状态。因为服务的初始化在q里没有完成Q所以这里的状态ؓ SERVICE_START_PENDINGQ? <li>dwControlsAcceptedQ这个域通知 SCM 服务接受哪个域。本文例子是允许 STOP ?SHUTDOWN h。处理控制请求将在第三步讨论Q? <li>dwWin32ExitCode ?dwServiceSpecificExitCodeQ这两个域在你终止服务ƈ报告退出细节时很有用。初始化服务时ƈ不退出,因此Q它们的gؓ 0Q? <li>dwCheckPoint ?dwWaitHintQ这两个域表C初始化某个服务q程时要30U以上。本文例子服务的初始化过E很短,所以这两个域的值都?0?</li> </ul> <p>  调用 SetServiceStatus 函数?SCM 报告服务的状态时。要提供 hStatus 句柄?ServiceStatus l构。注?ServiceStatus 一个全局变量Q所以你可以跨多个函C用它。ServiceMain 函数中,你给l构的几个域赋|它们在服务运行的整个q程中都保持不变Q比如:dwServiceType?br>  在报告了服务状态之后,你可以调?InitService 函数来完成初始化。这个函数只是添加一个说明性字W串到日志文件。如下面代码所C:</p> <pre>// 服务初始? int InitService() { int result; result = WriteToLog("Monitoring started."); return(result); }</pre> <p>  ?ServiceMain 中,?InitService 函数的返回倹{如果初始化有错Q因为有可能写日志文件失败)Q则服务状态置为终止ƈ退?ServiceMainQ?/p> <pre>error = InitService(); if (error) { // 初始化失败,l止服务 ServiceStatus.dwCurrentState = SERVICE_STOPPED; ServiceStatus.dwWin32ExitCode = -1; SetServiceStatus(hStatus, &ServiceStatus); // 退?ServiceMain return; }</pre> <p>如果初始化成功,则向 SCM 报告状态:</p> <pre>// ?SCM 报告q行状? ServiceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus (hStatus, &ServiceStatus);</pre> <p>接着Q启动工作@环。每五秒钟查询一个可用物理内存ƈ结果写入日志文件?br><br>?<a target=_blank><u><font color=#0000ff>Listing 1</font></u></a> 所C,循环一直到服务的状态ؓ SERVICE_RUNNING 或日志文件写入出错ؓ止。状态可能在 ControlHandler 函数响应 SCM 控制h时修攏V?br> <br><br><strong>W三步:处理控制h</strong><br><br>  在第二步中,你用 ServiceMain 函数注册了控制处理器函数。控制处理器与处理各U?Windows 消息的窗口回调函数非常类伹{它?SCM 发送了什么请求ƈ采取相应行动?br>  每次你调?SetServiceStatus 函数的时候,必须指定服务接收 STOP ?SHUTDOWN h?a target=_blank><u><font color=#0000ff>Listing 2</font></u></a> C了如何在 ControlHandler 函数中处理它们?br>  STOP h?SCM l止服务的时候发送的。例如,如果用户?#8220;服务”控制面板中手动终止服务。SHUTDOWN h是关闭机器时Q由 SCM 发送给所有运行中服务的请求。两U情늚处理方式相同Q?/p> <ul> <li>写日志文Ӟ监视停止Q? <li>?SCM 报告 SERVICE_STOPPED 状态; </li> </ul> <p>  ׃ ServiceStatus l构对于整个E序而言为全局量,ServiceStatus 中的工作循环在当前状态改变或服务l止后停止。其它的控制h如:PAUSE ?CONTINUE 在本文的例子没有处理?br>  控制处理器函数必L告服务状态,即便 SCM 每次发送控制请求的时候状态保持相同。因此,不管响应什么请求,都要调用 SetServiceStatus?br><br><img height=452 src="http://www.vckbase.com/document/journal/vckbase42/images/5stepsimg1.gif" width=690 border=0><br>图一 昄 MemoryStatus 服务的服务控刉?br><br><br><strong>W四步:安装和配|服?/strong><br><br>  E序~好了,之~译?exe 文g。本文例子创建的文g?MemoryStatus.exeQ将它拷贝到 C:\MyServices 文g夏Vؓ了在机器上安装这个服务,需要用 SC.EXE 可执行文Ӟ它是 Win32 Platform SDK 中附带的一个工兗(译者注QVisaul Studio .NET 2003 IDE 环境中也有这个工P具体存放位置在:C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\Bin\winntQ。用这个实用工具可以安装和U除服务。其它控制操作将通过服务控制面板来完成。以下是用命令行安装 MemoryStatus 服务的方法:</p> <pre>sc create MemoryStatus binpath= c:\MyServices\MemoryStatus.exe</pre> <p>  发出此创建命令。指定服务名和二q制文g的\径(注意 binpath= 和\径之间的那个I格Q。安装成功后Q便可以用服务控刉板来控制q个服务Q参见图一Q。用控制面板的工h启动和终止这个服务?br><br><img height=550 src="http://www.vckbase.com/document/journal/vckbase42/images/5stepsimg2.gif" width=542 border=0><br>图二 MemoryStatus 服务的属性窗?br><br>  MemoryStatus 的启动类型是手动Q也是说根据需要来启动q个服务。右键单击该服务Q然后选择上下文菜单中?#8220;属?#8221;菜单,此时昄该服务的属性窗口。在q里可以修改启动cd以及其它讄。你q可以从“常规”标签中启?停止服务。以下是从系l中U除服务的方法:</p> <pre>sc delete MemoryStatus</pre> <p>指定 “delete” 选项和服务名。此服务被标记为删除,下次襉K重启后Q该服务被完全U除?br><br><br><strong>W五步:试服务</strong><br><br>  从服务控刉板启?MemoryStatus 服务。如果初始化不出错,表示启动成功。过一会儿服务停止。检查一?C:\MyServices 文g夹中 memstatus.txt 文g的服务输出。在我的机器上输出是q样的:</p> <pre>Monitoring started. 273469440 273379328 273133568 273084416 Monitoring stopped.</pre> <p>  Z试 MemoryStatus 服务在出错情况下的行为,可以?memstatus.txt 文g讄成只诅R这样一来,服务应该无法启动?br>  L只读属性,启动服务Q在文件设成只诅R服务将停止执行Q因为此时日志文件写入失败。如果你更新服务控制面板的内容,会发现服务状态是已经停止?br> <br><br><strong>开发更大更好的服务E序</strong><br><br>  理解 Win32 服务的基本概念,使你能更好地?C++ 来设计包装类。包装类隐藏了对底层 Win32 函数的调用ƈ提供了一U舒适的通用接口。修?MemoryStatus E序代码Q创建满己需要的服务Qؓ了实现比本文例子所C的更复杂的Q务,你可以创建多U程的服务,作业划分成几个工作者线Eƈ?ServiceMain 函数中监视它们的执行?br> </p> </td> </tr> <tr> <td><img src="http://www.vckbase.com/image/paragraph.gif"> <strong>作者简?/strong><br>    <strong>Yevgeny Menaker</strong> 是一名有着过5q经验开发h员,作家?Linux N。过ȝ三年QYevgeny 专注于开发新的高U的 Internet 技术。他牵头~写了《Programming Perl in the .NET Environment》一书(Prentice-HallQ。此外,作ؓ Linux NQ他q在 Object Innovations 任职。Yevgeny Menaker 的联pL式是Qjeka_books@hotmail.com</td> </tr> </tbody> </table><img src ="http://www.shnenglu.com/colys/aggbug/24238.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/colys/" target="_blank">colys</a> 2007-05-16 19:56 <a href="http://www.shnenglu.com/colys/articles/24238.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>H口全屏代码http://www.shnenglu.com/colys/articles/24174.htmlcolyscolysTue, 15 May 2007 14:48:00 GMThttp://www.shnenglu.com/colys/articles/24174.htmlhttp://www.shnenglu.com/colys/comments/24174.htmlhttp://www.shnenglu.com/colys/articles/24174.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/24174.htmlhttp://www.shnenglu.com/colys/services/trackbacks/24174.html 全屏

 1 
 2  CMDIChildWnd* pChild=MDIGetActive();
 3  if(!pChild) return;
 4  m_bToolBarWasVisible=(m_wndToolBar.IsWindowVisible()!=0);
 5  m_wndToolBar.ShowWindow(SW_HIDE);//隐藏工具?/span>
 6  m_bStatusBarWasVisible=(m_wndStatusBar.IsWindowVisible()!=0);
 7  m_wndStatusBar.ShowWindow(SW_HIDE);//隐藏状态栏
 8 
 9  // first create the new toolbar
10  // this will contain the full-screen off button
11  m_pwndFullScreenBar=new CToolBar;
12  m_pwndFullScreenBar->Create(this);
13  m_pwndFullScreenBar->LoadToolBar(IDR_FULLSCREEN);//昄退出全屏工h
14  m_pwndFullScreenBar->SetBarStyle(m_pwndFullScreenBar->GetBarStyle() |
15   CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
16  // to look better:
17  m_pwndFullScreenBar->ModifyStyle(0, TBSTYLE_FLAT);
18  m_pwndFullScreenBar->EnableDocking(0);
19 
20  // place the full-screen off button somewhere:
21  CPoint pt(300,200);
22  FloatControlBar(m_pwndFullScreenBar,pt);
23  
24  // now save the old positions of the main and child windows
25  GetWindowRect(&m_mainRect);
26 
27  // remove the caption of the mainWnd:
28  LONG style=::GetWindowLong(m_hWnd,GWL_STYLE);
29  style&=~WS_CAPTION;
30  ::SetWindowLong(m_hWnd,GWL_STYLE,style);
31  int screenx=GetSystemMetrics(SM_CXSCREEN);
32  int screeny=GetSystemMetrics(SM_CYSCREEN);
33 
34  // resize:
35  SetWindowPos(NULL,0,0,screenx,screeny,SWP_NOZORDER);
36  //SetWindowPos(NULL,-5,-5,80,80,SWP_NOZORDER);
37  style=::GetWindowLong(pChild->m_hWnd,GWL_STYLE);
38  m_bChildMax=(style & WS_MAXIMIZE)?true:false;
39  // note here: m_bMainMax is not needed since m_hWnd only
40  // changed its caption
41  ///***************
42 
43  //Save the Original Menu and set menu to NULL
44     ASSERT(m_OrgMenu.GetSafeHmenu()==NULL);
45     CMenu* pOldMenu=GetMenu();
46     m_OrgMenu.Attach(pOldMenu->Detach());
47     SetMenu((CMenu*)NULL);
48 
49  //************
50  // and maximize the child window
51  // it will remove its caption, too.
52   //pChild->
53  this->ShowWindow (SW_SHOWMAXIMIZED);
54  style=::GetWindowLong(pChild->m_hWnd,GWL_STYLE);//获得H口风格
55  style&=~WS_CAPTION;
56  ::SetWindowLong(pChild->m_hWnd,GWL_STYLE,style); 
57  pChild->ShowWindow(SW_SHOWMAXIMIZED);
58 
59  //RecalcLayout();
60  
61 
62 

退出全?br>
 1ASSERT(m_OrgMenu.GetSafeHmenu()!=NULL);
 2    SetMenu(&m_OrgMenu);
 3    m_OrgMenu.Detach();
 4
 5    // You can use SaveBarState() in OnClose(),
 6    // so remove the newly added toolbar entirely
 7    // in order SaveBarState() not
 8    // to save its state. That is why I used dynamic
 9    // allocation
10    delete m_pwndFullScreenBar;
11    LONG style=::GetWindowLong(m_hWnd,GWL_STYLE);
12    style|=WS_CAPTION;
13    ::SetWindowLong(m_hWnd,GWL_STYLE,style);
14    if(m_bToolBarWasVisible)
15        m_wndToolBar.ShowWindow(SW_SHOW);
16    if(m_bStatusBarWasVisible)
17        m_wndStatusBar.ShowWindow(SW_SHOW);
18    MoveWindow(&m_mainRect);
19    RecalcLayout();
20    CMDIChildWnd* pChild=MDIGetActive();
21
22    style=::GetWindowLong(pChild->m_hWnd,GWL_STYLE);
23    style|=WS_CAPTION;
24    ::SetWindowLong(pChild->m_hWnd,GWL_STYLE,style);
25    // pchild can be NULL if the USER closed all the
26    // childs during Full Screen Mode:
27    if(pChild){
28        if(m_bChildMax)
29            MDIMaximize(pChild);
30        else MDIRestore(pChild);
31    }


colys 2007-05-15 22:48 发表评论
]]>
用C++控制DVD/CD驱动器的开?/title><link>http://www.shnenglu.com/colys/articles/24113.html</link><dc:creator>colys</dc:creator><author>colys</author><pubDate>Mon, 14 May 2007 13:51:00 GMT</pubDate><guid>http://www.shnenglu.com/colys/articles/24113.html</guid><description><![CDATA[在Windows资源览器中Q可在DVD/CD光驱图标上单击鼠标右键,选择"弹出"来打开光驱仓门Q你可能也发CQ菜单中q没?关闭"命o来关闭光驱。下面,p我们用程序来控制打开、关闭光驱?<br><br>  E序的主要工作部分ؓCD_OpenClose(BOOL bOpen, TCHAR cDrive)函数Q?br><br> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080"> 1</span> <span style="COLOR: #008000">//</span><span style="COLOR: #008000">cDrive是光qW,或?x01为默认驱动器?br></span><span style="COLOR: #008080"> 2</span> <span style="COLOR: #008000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">例如Q?br></span><span style="COLOR: #008080"> 3</span> <span style="COLOR: #008000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">CD_OpenCloseDrive(TRUE, 'G'); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">打开光驱G:<br></span><span style="COLOR: #008080"> 4</span> <span style="COLOR: #008000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">CD_OpenCloseDrive(FALSE, 'G'); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">关闭光驱G:<br></span><span style="COLOR: #008080"> 5</span> <span style="COLOR: #008000"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">CD_OpenCloseDrive(TRUE, 1); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">打开W一个逻辑光驱</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080"> 6</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080"> 7</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> CD_OpenCloseDrive(BOOL bOpenDrive, TCHAR cDrive)<br></span><span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000">{<br></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000"> MCI_OPEN_PARMS op;<br></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000"> MCI_STATUS_PARMS st;<br></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000"> DWORD flags;<br></span><span style="COLOR: #008080">12</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080">13</span> <span style="COLOR: #000000"> TCHAR szDriveName[</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">];<br></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000"> strcpy(szDriveName, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">X:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">15</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080">16</span> <span style="COLOR: #000000"> ::ZeroMemory(</span><span style="COLOR: #000000">&</span><span style="COLOR: #000000">op, </span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(MCI_OPEN_PARMS));<br></span><span style="COLOR: #008080">17</span> <span style="COLOR: #000000"> op.lpstrDeviceType </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (LPCSTR) MCI_DEVTYPE_CD_AUDIO;<br></span><span style="COLOR: #008080">18</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080">19</span> <span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(cDrive </span><span style="COLOR: #000000">></span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">20</span> <span style="COLOR: #000000"> {<br></span><span style="COLOR: #008080">21</span> <span style="COLOR: #000000">  szDriveName[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> cDrive;<br></span><span style="COLOR: #008080">22</span> <span style="COLOR: #000000">  op.lpstrElementName </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> szDriveName;<br></span><span style="COLOR: #008080">23</span> <span style="COLOR: #000000">  flags </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> MCI_OPEN_TYPE </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"> MCI_OPEN_TYPE_ID </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"> MCI_OPEN_ELEMENT</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"> MCI_OPEN_SHAREABLE;<br></span><span style="COLOR: #008080">24</span> <span style="COLOR: #000000"> }<br></span><span style="COLOR: #008080">25</span> <span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> flags </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> MCI_OPEN_TYPE </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"> MCI_OPEN_TYPE_ID </span><span style="COLOR: #000000">|</span><span style="COLOR: #000000"> MCI_OPEN_SHAREABLE;<br></span><span style="COLOR: #008080">26</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080">27</span> <span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">mciSendCommand(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,MCI_OPEN,flags,(unsigned </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&</span><span style="COLOR: #000000">op))<br></span><span style="COLOR: #008080">28</span> <span style="COLOR: #000000"> {<br></span><span style="COLOR: #008080">29</span> <span style="COLOR: #000000">  st.dwItem </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> MCI_STATUS_READY;<br></span><span style="COLOR: #008080">30</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080">31</span> <span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(bOpenDrive)<br></span><span style="COLOR: #008080">32</span> <span style="COLOR: #000000">   mciSendCommand(op.wDeviceID,MCI_SET,MCI_SET_DOOR_OPEN,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">33</span> <span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">34</span> <span style="COLOR: #000000">   mciSendCommand(op.wDeviceID,MCI_SET,MCI_SET_DOOR_CLOSED,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">35</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080">36</span> <span style="COLOR: #000000">  mciSendCommand(op.wDeviceID,MCI_CLOSE,MCI_WAIT,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">37</span> <span style="COLOR: #000000"> }<br></span><span style="COLOR: #008080">38</span> <span style="COLOR: #000000">}</span></div> <br><br> Z方便对多个光p行操作,d了下面这个函敎ͼ其会调用上面的CD_OpenCloseDrive()函数Q?br><br> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080"> 1</span> <span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> CD_OpenCloseAllDrives(BOOL bOpenDrives)<br></span><span style="COLOR: #008080"> 2</span> <span style="COLOR: #000000">{<br></span><span style="COLOR: #008080"> 3</span> <span style="COLOR: #000000"> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">判定所有光驱,q个打开或关闭?/span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080"> 4</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> nPos </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080"> 5</span> <span style="COLOR: #000000"> UINT nCount </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080"> 6</span> <span style="COLOR: #000000"> TCHAR szDrive[</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">];<br></span><span style="COLOR: #008080"> 7</span> <span style="COLOR: #000000"> strcpy(szDrive, </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">?:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000"> DWORD dwDriveList </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> ::GetLogicalDrives ();<br></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> (dwDriveList) {<br></span><span style="COLOR: #008080">12</span> <span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (dwDriveList </span><span style="COLOR: #000000">&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">13</span> <span style="COLOR: #000000">  {<br></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000">   szDrive[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0x41</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> nPos;<br></span><span style="COLOR: #008080">15</span> <span style="COLOR: #000000">   </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(::GetDriveType(szDrive) </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> DRIVE_CDROM)<br></span><span style="COLOR: #008080">16</span> <span style="COLOR: #000000">    CD_OpenCloseDrive(bOpenDrives, szDrive[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]);<br></span><span style="COLOR: #008080">17</span> <span style="COLOR: #000000">  }<br></span><span style="COLOR: #008080">18</span> <span style="COLOR: #000000">  dwDriveList </span><span style="COLOR: #000000">>>=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">19</span> <span style="COLOR: #000000">  nPos</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">20</span> <span style="COLOR: #000000"> }<br></span><span style="COLOR: #008080">21</span> <span style="COLOR: #000000">}</span></div> <br> 最后一点,别忘了在E序开头包括Mmsystem.h头文Ӟ及在链接选项里写上Winmm.lib?br><img src ="http://www.shnenglu.com/colys/aggbug/24113.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/colys/" target="_blank">colys</a> 2007-05-14 21:51 <a href="http://www.shnenglu.com/colys/articles/24113.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>q制介绍http://www.shnenglu.com/colys/articles/22816.htmlcolyscolysWed, 25 Apr 2007 11:35:00 GMThttp://www.shnenglu.com/colys/articles/22816.htmlhttp://www.shnenglu.com/colys/comments/22816.htmlhttp://www.shnenglu.com/colys/articles/22816.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/22816.htmlhttp://www.shnenglu.com/colys/services/trackbacks/22816.html
1. 十进制数
十进制数的两个主要特点:

⑴有十个不同的数字:
0?/span>1?/span>2?/span>3?/span>4?/span>5?/span>6?/span>7?/span>8?/span>9;

⑵逢十q一的进位法,10是十q制数的基数(q制中所用不同数字的个数)?br>
(
1993)10=1×103+9×102+9×101+3×100(每位上的pL只在0?中取?

2. 二进制数
二进制数的两个主要特点:

⑴有两个不同的数字:
0?/span>1;

⑵逢二q一的进位法,2是二q制数的基数?br>
(
1011)2=1×23+0×22+1×21+1×20(每位上的pL只在0?中取?

3. 八进制数
八进制数的两个主要特点:

⑴采用八个不同的数字Q?/span>0?/span>1?/span>2?/span>3?/span>4?/span>5?/span>6?/span>7;

⑵逢八q一的进位法,8是八q制数的基数?br>
(
1725)8=1×83+7×82+2×81+5×80(每位上的pL只在0?中取?

4. 十六q制
十六q制数的两个主要特点Q?br>
⑴有十六个不同的数字Q?/span>0?/span>1?/span>2?/span>3?/span>4?/span>5?/span>6?/span>7?/span>8?/span>9、A、B、C、D、E、F(其中后六个数字符号其值对应于十进制的10,11,12,13,14,15Q也有选用S,T,U,V,W,X的记?;

⑵逢十六进一的进位法,16是十六进制数的基数?br>
(B56E)
16=163+5×162+6×161+160=11×163+5×162+6×161+14×160

二进制换ؓ十六q制是这?
先把二进制从低位Q也是从右到左Q按四位一l分开Q分到最后不够四位的也按一l来?/span>
分好以后再把每组的二q制换算成十六进Ӟ之后再接换算好的l合h可以了?br>
如:  1101110111010

分组后是:   1Q?011Q?011Q?010

每组换算成十六进制是1QB,B,A l合?BBA



colys 2007-04-25 19:35 发表评论
]]>
[导入]设计模式学习?SingletonQ一Q?/title><link>http://www.shnenglu.com/colys/articles/22552.html</link><dc:creator>colys</dc:creator><author>colys</author><pubDate>Sat, 21 Apr 2007 16:02:00 GMT</pubDate><guid>http://www.shnenglu.com/colys/articles/22552.html</guid><wfw:comment>http://www.shnenglu.com/colys/comments/22552.html</wfw:comment><comments>http://www.shnenglu.com/colys/articles/22552.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/colys/comments/commentRss/22552.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/colys/services/trackbacks/22552.html</trackback:ping><description><![CDATA[<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">d接触</span><span lang=EN-US style="FONT-SIZE: 9pt">ACE</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时学习了一D|间的设计模式Q?/span><span style="FONT-SIZE: 9pt"> </span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">单地看了</span><span lang=EN-US style="FONT-SIZE: 9pt">Gof</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的设计模式,</span><span lang=EN-US style="FONT-SIZE: 9pt"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">l合</span><span lang=EN-US style="FONT-SIZE: 9pt">ACE</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">大略的看?/span><span lang=EN-US style="FONT-SIZE: 9pt">POSA1</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q?/span><span lang=EN-US style="FONT-SIZE: 9pt"> POSA2</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">?/span><span lang=EN-US style="FONT-SIZE: 9pt"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对设计模式的理解q是很肤,</span><span style="FONT-SIZE: 9pt"> </span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">H然x入地学习设计模式Q?/span><span style="FONT-SIZE: 9pt"> </span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Ҏ一U模?/span><span lang=EN-US style="FONT-SIZE: 9pt"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">都辅助相关的</span><span lang=EN-US style="FONT-SIZE: 9pt">code</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来理解,</span><span style="FONT-SIZE: 9pt"> </span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">q把设计模式?/span><span lang=EN-US style="FONT-SIZE: 9pt">MFC</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q?/span><span lang=EN-US style="FONT-SIZE: 9pt"> ACE</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q?/span><span lang=EN-US style="FONT-SIZE: 9pt"> cppunit</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">{框架联pv来,</span><span lang=EN-US style="FONT-SIZE: 9pt"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">更好地理解和应用q些~程的框Ӟq有</span><span lang=EN-US style="FONT-SIZE: 9pt">log4plus</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">{)</span><span lang=EN-US style="FONT-SIZE: 9pt"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US style="FONT-SIZE: 9pt"><o:p> </o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">今天ȝ一下简单的单g模式Q?/span><span lang=EN-US style="FONT-SIZE: 9pt"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; LINE-HEIGHT: 120%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><strong><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; mso-font-kerning: 0pt">Singleton(</span></strong><strong><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">单g</span></strong><strong><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; mso-font-kerning: 0pt">)</span></strong><strong><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">——对象创建型模式</span></strong><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; LINE-HEIGHT: 120%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">保证一个类仅有一个实例,q提供一个访问它的全局讉K炏V?span lang=EN-US><o:p></o:p></span></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; LINE-HEIGHT: 120%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><strong><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">1</span></strong><strong><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">·典型</span></strong><strong><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; mso-font-kerning: 0pt">Singleton</span></strong><strong><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">c?/span></strong><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">Q?span lang=EN-US><o:p></o:p></span></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: 新宋? mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt"><o:p> </p> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">class Singleton<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     static Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Instance();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>protected:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     Singleton();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     static Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> _instance;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Singleton::_instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Singleton::Instance()<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_instance </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     {<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>         _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Singleton;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     }<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     return _instance;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span></div> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align=left></o:p></span> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; LINE-HEIGHT: 120%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">客户仅通过</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; mso-font-kerning: 0pt">Instance</span><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">成员函数讉Kq个单g。变?/span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; mso-font-kerning: 0pt">_instance</span><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">初始化ؓ</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; mso-font-kerning: 0pt">0</span><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">Q而静态成员函?/span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; mso-font-kerning: 0pt">Instance</span><span style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">q回该变量倹{注意:构造器是保护型的,保证了仅有一个实例被创徏?span lang=EN-US><o:p></o:p></span></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; LINE-HEIGHT: 120%; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; LINE-HEIGHT: 120%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p> </o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">q种方式的实现对于线E来说ƈ不是安全的,因ؓ在多U程的环境下有可能得?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">cȝ多个实例。如果同时有两个U程d断(</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">_instance == null</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">Q,q且得到的结果ؓ真,q时两个U程都会创徏c?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">的实例,q样p背了</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">模式的原则。实际上在上qC码中Q有可能在计出表达式的g前,对象实例已经被创建,但是内存模型q不能保证对象实例在W二个线E创Z前被发现?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> <o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> </span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">该实现方式主要有两个优点Q?#183;׃实例是在</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> <strong><span lang=EN-US>Instance</span></strong><span lang=EN-US> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">属性方法内部创建的Q因此类可以使用附加功能Q例如,对子c进行实例化Q,即它可能引入不惌的依赖性?#183;</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">  </span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">直到对象要求产生一个实例才执行实例化;q种ҎUCؓ</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">“</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">惰性实例化</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">”</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">。惰性实例化避免了在应用E序启动时实例化不必要的</span><strong><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> singleton</span></strong><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><strong style="mso-bidi-font-weight: normal"><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">2</span></strong><strong style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">·U程安全?/span></strong><strong style="mso-bidi-font-weight: normal"><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">singleton<o:p></o:p></span></strong></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma"></p> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">class Singleton<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     static Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Instance();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>protected:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     Singleton();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     static Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> _instance;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     static Cmutext _mutex;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Singleton::_instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Singleton::Instance()<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     _mutex.acque();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_instance </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     {<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>         _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Singleton;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     }<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     _mutex.release();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     return _instance;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span></div> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left> </span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">q种方式的实现对于线E来说是安全的。我们首先创Z一个进E辅助对象,U程在进入时先对辅助对象加锁然后再检对象是否被创徏Q这样可以确保只有一个实例被创徏Q因为在同一个时d了锁的那部分E序只有一个线E可以进入。这U情况下Q对象实例由最先进入的那个U程创徏Q后来的U程在进入时Q?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma">_instence == null</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">Qؓ假,不会再去创徏对象实例了。但是这U实现方式增加了额外的开销Q损׃性能?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma"><o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><strong><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma">3</span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">Q双重锁?/span></strong><strong><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma"><o:p></o:p></span></strong></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma"><span style="mso-spacerun: yes"> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">q种实现方式对多U程来说是安全的Q同时线E不是每ơ都加锁Q只有判断对象实例没有被创徏时它才加锁,有了我们上面W一部分的里面的分析Q我们知道,加锁后还得再q行对象是否已被创徏的判断。它解决了线Eƈ发问题,同时避免在每?/span><span style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma"> <strong><span lang=EN-US style="FONT-FAMILY: Tahoma">Instance</span></strong><span lang=EN-US> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">属性方法的调用中都出现独占锁定。它q允许您实例化延迟到第一ơ访问对象时发生。实际上Q应用程序很需要这U类型的实现。大多数情况下我们会用静态初始化。这U方式仍然有很多~点Q无法实现gq初始化?br><br></p> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">class Singleton<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     static Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Instance();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>protected:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     Singleton();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     static Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> _instance;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     static CMutex _mutex;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Singleton::_instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>Singleton</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> Singleton::Instance()<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(_instance </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     {<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>         _mutex.acque();<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>         _instance </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Singleton;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>         _mutex.release<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     }<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>     return _instance;<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.shnenglu.com/Images/OutliningIndicators/None.gif" align=top></span></div> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><br></p> </span> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma"><br>实现要点</span></strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> <span lang=EN-US><o:p></o:p></span></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><span style="mso-spacerun: yes"> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">·</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">模式是限制而不是改q类的创建?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> <o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><span style="mso-spacerun: yes"> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">·</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">cM的实例构造器可以讄?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Protected</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">以允许子cL生?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><span style="mso-spacerun: yes"> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">·</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">模式一般不要支?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Icloneable</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">接口Q因可能D多个对象实例Q与</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">模式的初衯背?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><span style="mso-spacerun: yes"> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">·</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">模式一般不要支持序列化Q这也有可能D多个对象实例Q这也与</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">模式的初衯背?/span><span style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> <span lang=EN-US><o:p></o:p></span></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><span style="mso-spacerun: yes"> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">·</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">只考虑了对象创建的理Q没有考虑到销毁的理Q就支持垃圾回收的^台和对象的开销来讲Q我们一般没必要对其销毁进行特D的理?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><span style="mso-spacerun: yes"> </span></span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">·理解和扩?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">模式的核心是</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">“</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">如何控制用户使用</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">new</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">对一个类的构造器的Q意调?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">”</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-font-kerning: 0pt; mso-bidi-font-family: Tahoma">?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> <o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"> <o:p></o:p></span></p> <p class=MsoNormal style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">ȝQ?/span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma"> </span></strong><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Tahoma">Singleton</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma; mso-bidi-font-family: Tahoma">设计模式是一个非常有用的机制Q可用于在面向对象的应用E序中提供单个访问点?/span><span lang=EN-US style="FONT-SIZE: 9pt"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">应该注意的几?/span></strong><strong><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">:</span></strong><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br>    1,</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">我们不应该来序列化和反序列化用单件模式实现的对象</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">,</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">否则多次反序列化则可以创建多的实?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">,</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">q与单g模式是相矛盾?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">.<br>    2,</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">我们不应该克隆用单g模式实现的对?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">,</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">否则多次克隆则可以创建多的实?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">,</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">q与单g模式是相矛盾?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">.<br>    3,</span><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">在多U程环境中用单件模式时要小?/span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">.<br style="mso-special-character: line-break"><br style="mso-special-character: line-break"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 9pt; COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">关于</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: red; FONT-FAMILY: Verdana">ACE</span><span style="FONT-SIZE: 9pt; COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">中单件模?/span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: red; FONT-FAMILY: Verdana">ACE_Singleton</span><span style="FONT-SIZE: 9pt; COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">的设计和应用可以参考一博友的文章,</span><span style="FONT-SIZE: 9pt; COLOR: red; FONT-FAMILY: Verdana"> </span><span style="FONT-SIZE: 9pt; COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">感觉写的很好</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: red; FONT-FAMILY: Verdana"><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><a ><u><font color=#800080>http://blog.csdn.net/joise/archive/2006/09/29/1305849.aspx</font></u></a><o:p></o:p></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><o:p> </o:p></span></p> <img height=1 src="http://www.shnenglu.com/Galaxy/aggbug/22502.html" width=1><br><br> <div align=right><a style="TEXT-DECORATION: none" href="http://www.shnenglu.com/Galaxy/" target=_blank>Galaxy</a> 2007-04-21 17:18 <a style="TEXT-DECORATION: none" href="http://www.shnenglu.com/Galaxy/archive/2007/04/21/22502.html#Feedback" target=_blank>发表评论</a></div> <br>文章来源:<a href="http://www.shnenglu.com/Galaxy/archive/2007/04/21/22502.html">http://www.shnenglu.com/Galaxy/archive/2007/04/21/22502.html</a><img src ="http://www.shnenglu.com/colys/aggbug/22552.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/colys/" target="_blank">colys</a> 2007-04-22 00:02 <a href="http://www.shnenglu.com/colys/articles/22552.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[导入]U学计算相关的c++?/title><link>http://www.shnenglu.com/colys/articles/22553.html</link><dc:creator>colys</dc:creator><author>colys</author><pubDate>Sat, 21 Apr 2007 16:02:00 GMT</pubDate><guid>http://www.shnenglu.com/colys/articles/22553.html</guid><wfw:comment>http://www.shnenglu.com/colys/comments/22553.html</wfw:comment><comments>http://www.shnenglu.com/colys/articles/22553.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/colys/comments/commentRss/22553.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/colys/services/trackbacks/22553.html</trackback:ping><description><![CDATA[<p>Blitz++ </p> <p>参考网站:<a >http://www.oonumerics.org/blitz/</a></p> <p>Blitz++ 是一个高效率的数D函数库Q它的设计目的是希望建立一套既具像C++ 一h便,同时又比Fortran速度更快的数D环境。通常Q用C++所写出的数值程序,?Fortran?0%左右Q因此Blitz++正是要改掉这个缺炏V方法是利用C++的template技术,E序执行甚至可以比Fortran更快。Blitz++目前仍在发展中,对于常见的SVDQFFTsQQMRES{常见的U性代数方法ƈ不提供,不过使用者可以很Ҏ地利用Blitz++所提供的函数来构徏?</p> <p>POOMA </p> <p>参考网站:<a >http://www.codesourcery.com/pooma/pooma</a></p> <p>POOMA是一个免费的高性能的C++库,用于处理q行式科学计。POOMA的面向对象设计方便了快速的E序开发,对ƈ行机器进行了优化以达到最高的效率Q方便在工业和研I环境中使用?</p> <p>MTL </p> <p>参考网站:<a >http://www.osl.iu.edu/research/mtl/</a></p> <p>Matrix Template Library(MTL)是一个高性能的泛型组件库Q提供了各种格式矩阵的大量线性代数方面的功能。在某些应用使用高性能~译器的情况下,比如Intel的编译器Q从产生的汇~代码可以看出其与手写几乎没有两L效能?</p> <p>CGAL </p> <p>参考网站:<a >www.cgal.org</a></p> <p>Computational Geometry Algorithms Library的目的是把在计算几何斚w的大部分重要的解x案和Ҏ以C++库的形式提供l工业和学术界的用户?<br></p> <img height=1 src="http://www.shnenglu.com/Galaxy/aggbug/20725.html" width=1><br><br> <div align=right><a style="TEXT-DECORATION: none" href="http://www.shnenglu.com/Galaxy/" target=_blank>Galaxy</a> 2007-03-27 17:59 <a style="TEXT-DECORATION: none" href="http://www.shnenglu.com/Galaxy/archive/2007/03/27/20725.html#Feedback" target=_blank>发表评论</a></div> <br>文章来源:<a href="http://www.shnenglu.com/Galaxy/archive/2007/03/27/20725.html">http://www.shnenglu.com/Galaxy/archive/2007/03/27/20725.html</a><img src ="http://www.shnenglu.com/colys/aggbug/22553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/colys/" target="_blank">colys</a> 2007-04-22 00:02 <a href="http://www.shnenglu.com/colys/articles/22553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[导入]核心对象Ȁ发状态的意义http://www.shnenglu.com/colys/articles/21023.htmlcolyscolysSat, 31 Mar 2007 15:03:00 GMThttp://www.shnenglu.com/colys/articles/21023.htmlhttp://www.shnenglu.com/colys/comments/21023.htmlhttp://www.shnenglu.com/colys/articles/21023.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/21023.htmlhttp://www.shnenglu.com/colys/services/trackbacks/21023.html“Ȁ?#8221; signaled 对于不同的核心对象有不同的意?/span>

Thread U程Q当U程l束ӞU程对象卌Ȁ发。当U程q在q行Ӟ则对象处于未Ȁ发状态?/span>

Process q程Q当q程l束Ӟq程对象卌Ȁ发。当q程q在q行Ӟ则对象处于未Ȁ发状态?/span>

Change Notification Q当一个特定的盘子目录中发生一件特别的变化Ӟ此对象即被激发。此对象pȝ FindFirstChangeNotification() 产生

Console Input Q当 console H口的输入缓冲区中有数据可用Ӟ此对象将处于Ȁ发状态?/span> CreateFile Q)?/span> GetStdFile Q)两函数可以获?/span> console handle ?/span>

Event Q?/span> Event 对象的状态直接受控于应用E序所使用的三?/span> Win32 函数Q?/span> SetEvent Q)Q?/span> PulseEvent Q)Q?/span> ResetEvent Q)?/span> CreateEvent Q)?/span> OpenEvent Q)都可以传回一?/span> event object handle ?/span> Event 对象的状态也可以被操作系l设定——如果用于“ overlapped ”操作时?/span>

Mutex Q如?/span> mutex 没有被Q何线E拥有,他就是处于激发状态。一旦一个等?/span> mutex 的函数返回了Q?/span> mutex 也就自动重置为未Ȁ发状态?/span> CreateMutex Q)?/span> OpenMutex Q)都可以获得一?/span> Mutext ?/span> handle ?/span>

Semaphore Q?/span> Semaphore 有点?/span> mutex Q但他有个计数器Q可以约束其拥有者(U程Q的个数。当计数器内容大?/span> 0 Ӟ semaphore 处于Ȁ发状态,当计数器内容{于 0 Ӟ semaphore 处于未激发状态?/span> CreateSemaphore Q)?/span> OpenSemaphore Q)可以传回一?/span> semaphore handle ?/span>



colys 2007-03-31 23:03 发表评论
]]>
C++ Builder下在一个窗体的panel中显C加一个窗体的控ghttp://www.shnenglu.com/colys/articles/21021.htmlcolyscolysSat, 31 Mar 2007 14:57:00 GMThttp://www.shnenglu.com/colys/articles/21021.htmlhttp://www.shnenglu.com/colys/comments/21021.htmlhttp://www.shnenglu.com/colys/articles/21021.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/21021.htmlhttp://www.shnenglu.com/colys/services/trackbacks/21021.html/*
 *已知两窗体TfrmSetting?frmModifyPath
 *昄frmModifyPath的TPanel控gPanContent到TfrmSetting的TPanel控gpanClient
 */

int TfrmSetting::ShowModifyPathWin()
{
    if(frmModifyPath)
    {
        if(frmModifyPath->PanContent ->Parent !=panClient)
        {
            frmModifyPath->PanContent->Parent= panClient;
            frmModifyPath->PanContent->Align=alClient;        
        }
    }
}


colys 2007-03-31 22:57 发表评论
]]>
一道算法面试题http://www.shnenglu.com/colys/articles/20418.htmlcolyscolysFri, 23 Mar 2007 02:41:00 GMThttp://www.shnenglu.com/colys/articles/20418.htmlhttp://www.shnenglu.com/colys/comments/20418.htmlhttp://www.shnenglu.com/colys/articles/20418.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/20418.htmlhttp://www.shnenglu.com/colys/services/trackbacks/20418.html题目Q?/p>

?到N(100000)中Q意拿掉两个数Q把剩下?9998个数序打ؕQƈ且放入数lA中。要求只扫描一遍数l,把这两个数找出来。可以用最C过5个局部变量,不能用数l变量,q且不能改变原数l的倹{?br />



colys 2007-03-23 10:41 发表评论
]]>
ASSERT( booleanExpression ) 的作?/title><link>http://www.shnenglu.com/colys/articles/19665.html</link><dc:creator>colys</dc:creator><author>colys</author><pubDate>Mon, 12 Mar 2007 14:15:00 GMT</pubDate><guid>http://www.shnenglu.com/colys/articles/19665.html</guid><wfw:comment>http://www.shnenglu.com/colys/comments/19665.html</wfw:comment><comments>http://www.shnenglu.com/colys/articles/19665.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/colys/comments/commentRss/19665.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/colys/services/trackbacks/19665.html</trackback:ping><description><![CDATA[<a name="16773806">  <div id="fjdvrfr" class="f14">ASSERT( booleanExpression )Q?<br />首先QbooleanExpression 参数是一个bool表达式?<br />用法Q?<br />当程序运行到该语句的时候,E序会检查booleanExpression q个表达式是真还是假?<br />如果条gW合Q程序l运行下面的代码Q?<br />如果是不W合Q那么持l运行会被卡在这里。不往下面赎ͼq有E序弹出错误对话框,指示是由于booleanExpression q个条gW合D的报错?<br />作用Q?<br />ASSERT(booleanExpression )语句一般用来检查一些必ȝ合的条gQ如果不W合条gQ则不让E序l箋q行下去?<br /><br />比如Q?<br />一个班?5个hQ有一个函数可以对班上?5个hq行处理Q一个单独处理一个同学也可以Q也可以同时处理多个同学。函数申明ؓQCONTROLSTUDENT(int number);其中number处理的学生的个数?<br />在用CONTROLSTUDENT函数前,一般我们会使用 <br />ASSERT(number<=55); <br />CONTROLSTUDENT(number); <br />q样可以保证输入的学生数目绝对小于等?5个h?<br />如果输入的number参数大于55Q程序将报错Q不执行?<br /><br />ȝQ该指o可以用来做ؓ某些条g的防护,避免不符合条件的东西产生DE序的崩溃?</div><div id="ldnlbnx" class="gray" align="right"></div></a> <div class="lxbvzbt" id="Lg"></div><a name="16775737"><div id="jrfnlbl" class="f14">只有在生成DEBUG码时ASSERT()才v作用. <br /><br />在生成Release码时~译器会跌ASSERT(). <br /><br />ASSERT()用来查上面运行结果有无错,例如送返的指针对不对,表达式返回值是不是"?,有错则打出有关信息ƈ退出程? </div></a><img src ="http://www.shnenglu.com/colys/aggbug/19665.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/colys/" target="_blank">colys</a> 2007-03-12 22:15 <a href="http://www.shnenglu.com/colys/articles/19665.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数组的引?http://www.shnenglu.com/colys/articles/19598.htmlcolyscolysMon, 12 Mar 2007 01:24:00 GMThttp://www.shnenglu.com/colys/articles/19598.htmlhttp://www.shnenglu.com/colys/comments/19598.htmlhttp://www.shnenglu.com/colys/articles/19598.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/19598.htmlhttp://www.shnenglu.com/colys/services/trackbacks/19598.html        象如下定义就得到一个数l的引用
        cd?Q?amp;变量明)[N]Q?br />       
        实例
        int int_array[10];
        int (&int_ref)[10] = int_array;
        q样得C一个数l的应用

        在函数的声明中用数组的引用定义,׃怕数l退化了。如?br />        for_each( int (&int_ref)[10] )
        {
                 for( int i=0; i<10; ++i )
                         std::cout << int_ref[i] << std::endl;
         }

         int main( int argc, char* argv[] )
         {
                 int int_array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
        
                 for_each( int_array );
                 return 0;
          }

          在上面的代码中,如果你传入不?0个尺寸的数组Q是~译通不q的。代码的安全性提高了。 ?

         惌定义一个数l引用类型,Ҏ如下
         typedef cd?(&数组引用cd?[N];

         实例
         typedef int (&Array_Ref)[10];
         Array_Ref是一个数l的引用cd了?br />



colys 2007-03-12 09:24 发表评论
]]>
lMSN Messager装个钩子[转蝲]http://www.shnenglu.com/colys/articles/18554.htmlcolyscolysThu, 08 Feb 2007 12:47:00 GMThttp://www.shnenglu.com/colys/articles/18554.htmlhttp://www.shnenglu.com/colys/comments/18554.htmlhttp://www.shnenglu.com/colys/articles/18554.html#Feedback0http://www.shnenglu.com/colys/comments/commentRss/18554.htmlhttp://www.shnenglu.com/colys/services/trackbacks/18554.html最q研I怎么样用HOOK拦截其他应用E序的消息,于是动手写了一个钩子程序来挂到最常用的通讯及时通讯工具MSNQ虽然没有什么实际意义,但作为学习研I却能够帮助我们理解利用HOOK是怎么样将自己~写的DLL注入已经存在的程序空间中的?br />

我们需要做的是通过我们自己~写的应用程序去拦截别h写好的应用程序消息,实际上这是在两个q程之间q行的,隑ֺ在q里Q如果是同一个进E什么都好办Q只要将pȝ响应WINDOWS消息的处理函C改ؓ我们自己~写的函数就可以Q但现在不能q么做,因ؓ两个q程有各自的q程地址I间Q理Z你没有办法直接去讉K别的q程的地址I间Q那么怎么办来Q办法还是很多的Q这里仅仅介l通过HOOK来达到目的?/p>

需要拦截别的应用程序的消息Q需要利用将自己~写的DLL注入到别人的DLL地址I间中才可以辑ֈ拦截别h消息的目的。只有将我们的DLL插入到别的应用程序的地址I间中才能够对别的应用程序进行操作,HOOK帮助我们完成了这些工作,我们只需要用HOOK来拦截指定的消息Qƈ提供必要的处理函数就行了。我们这里介l拦截在MSN聊天对话框上的鼠标消息,对应的HOOKcd是WH_MOUSE?/p>

首先我们要徏立一个用来HOOK的DLL。这个DLL的徏立和普通的DLL建立没有什么具体的区别Q不q我们这里提供的Ҏ有写不同。这里用隐式导入DLL的方法。代码如下:

头文?/p>

#pragma once
#ifndef MSNHOOK_API
#define MSNHOOK_API __declspec(dllimport)
#endif

MSNHOOK_API BOOL WINAPI SetMsnHook(DWORD dwThreadId);//安装MSN钩子函数
MSNHOOK_API void WINAPI GetText(int &x,int &y,char ** ptext);//安装MSN钩子函数
MSNHOOK_API HWND WINAPI GetMyHwnd();//安装MSN钩子函数

==================================================

DLL 的CPP文g

#include "stdafx.h"
#include "MSNHook.h"
#include <stdio.h>

// 下面几句的含义是告诉~译器将各变量放入它自己的数据共享节?/p>

#pragma data_seg("Shared")
HHOOK g_hhook = NULL;
DWORD g_dwThreadIdMsn = 0;
POINT MouseLoc={0,0};
char text[256]={0};
HWND g_Hwnd = NULL;
#pragma data_seg()

//告诉~译器设|共享节的访问方式ؓQ读Q写Q共?/p>

#pragma comment(linker,"/section:Shared,rws")

HINSTANCE g_hinstDll = NULL;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hinstDll = (HINSTANCE)hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

LRESULT WINAPI GetMsgProc(int nCode,WPARAM wParam, LPARAM lParam);

BOOL WINAPI SetMsnHook(DWORD dwThreadId)
{
OutputDebugString("SetMsnHook");
BOOL fOK = FALSE;
if(dwThreadId != 0)
{
OutputDebugString("SetMsnHook dwThreadId != 0");
g_dwThreadIdMsn = GetCurrentThreadId();

//安装WM_MOUSE钩子和处理函数GetMsgProc
g_hhook = SetWindowsHookEx(WH_MOUSE,GetMsgProc,g_hinstDll,dwThreadId);
fOK = (g_hhook != NULL);
if(fOK)
{
fOK = PostThreadMessage(dwThreadId,WM_NULL,0,0);
}
else
{
fOK = UnhookWindowsHookEx(g_hhook);
g_hhook = NULL;
}
}
return(fOK);
}

LRESULT WINAPI GetMsgProc(int nCode,WPARAM wParam, LPARAM lParam)
{

char temp[20];
sprintf(temp,"%dn",nCode);
OutputDebugString("temp");
if (nCode==HC_ACTION)
{
MOUSEHOOKSTRUCT *l=(MOUSEHOOKSTRUCT *)lParam;
MouseLoc=l->pt; //送鼠标位|?br />
//char text[256] = "";
HWND hWnd = WindowFromPoint(l->pt);
if(hWnd)
{
//GetWindowText(hWnd,text,256);
SendMessage(hWnd,WM_GETTEXT,256,(LPARAM)(LPCTSTR)text);
// strcpy(text,"123455555");
SendMessage(hWnd,WM_SETTEXT,256,(LPARAM)(LPCTSTR)text);
g_Hwnd = hWnd;
}
//SendMessage(WindowFromPoint(l->pt),WM_GETTEXT,256,(LPARAM)(LPCTSTR)psw);
}

return(CallNextHookEx(g_hhook,nCode,wParam,lParam));
}

void WINAPI GetText(int &x,int &y,char ** ptext)
{
x = MouseLoc.x;
y = MouseLoc.y;
*ptext = text;
}

HWND WINAPI GetMyHwnd()
{
return g_Hwnd;
}

上面是处理钩子的DLL代码Q下面我们要让这个DLL起作用还需要一个启动部分,通过q个启动部分我们才能让我们的钩子函数真正的注入到pȝ其他函数中。我们这里用个对话框的E序Q程序非常简单:一个按钮用来启动钩子,一个用来停止,一个TIMER用来h昄Q还有一个EDITBOX用来接受信息?/p>

E序如下Q?/p>

//包含DLL函数导出的头文g
#include "MSNHook.h"

//隐式导入

#pragma comment(lib,"MSNHook.lib")

//声明导入函数

__declspec(dllimport) BOOL WINAPI SetMsnHook(DWORD dwThreadId);
__declspec(dllimport) void WINAPI GetText(int &x,int &y,char ** ptext);
__declspec(dllimport) HWND WINAPI GetMyHwnd();//安装MSN钩子函数

void CTestMSNHookDlg::OnBnClickedOk()
{

//通过SPY++可以看到MSN聊天对话框窗口类是IMWindowClassQ通过q个得到该窗口句?br />CWnd *pMsnWin = FindWindow(TEXT("IMWindowClass"),NULL);
if(pMsnWin == NULL) return ;

//通过H口句柄得到对应的线E的ID
SetMsnHook(GetWindowThreadProcessId(pMsnWin->GetSafeHwnd(),NULL));
MSG msg;
GetMessage(&msg,NULL,0,0);
SetTimer(101,100,NULL);

}

void CTestMSNHookDlg::OnTimer(UINT_PTR nIDEvent)
{

//h消息
char * pText = NULL;
int x = 0,y = 0;
GetText(x,y,&pText);
if(x ==0 && y ==0) return ;
m_Edit.Format("%d:%d:%s",x,y,pText);
//m_Edit = pText;
UpdateData(FALSE);

HWND hWnd = GetMyHwnd();
CWnd * pWnd = CWnd::FromHandle(hWnd);
pWnd->GetWindowText(m_Edit);
CDialog::OnTimer(nIDEvent);
}

void CTestMSNHookDlg::OnBnClickedButton1()
{

//关闭
KillTimer(101);
SetMsnHook(0);
OnCancel();
}

好了Q基本上p些了。这里有个问题,我本惛_到MSN用户聊天时输入的聊天信息Q这里通过WM_GETTEXT消息的不刎ͼ如果有知道的朋友告诉一声?/p>

colys 2007-02-08 20:47 发表评论
]]>
þþ뾫Ʒպ˳| 91þþþþۺ| þùƷվ| պŷۺϾþӰԺDs| þþþ޾Ʒվ| ޾ƷþþþþĻ| ƷþavĻ| Ʒ޾þþþþ| ŷһþþ| 99þóĻ| þþþùƷ鶹ARӰԺ| ٸþþþþñŪ߳| þþƷ޾Ʒŷ| ŮHҳþþ| þþƷһ| þþƷ99þþ| ޹Ʒþ| Ʒžžžþþž| þĻavŮ| һƷþ| 99þþƷҹһ| þþAVҰ| þùƷ͵99| 99reþþƷҳ2020| þþù׮| ?VþþƷ| 88þþƷһëƬ| ޺ݺۺϾþþþ| ޾Ʒtvþþþ| þþƷҹɫA| þۺϾɫۺ97_þþ| ޹Ʒþþϼ2| þþþƷר | þùƷ԰| AAAþþþƷƬ| þþƷɧ| þۺϹ׾Ʒ| 97Ʒ97þþþþ| ƷһþaaaƬ| þþƷaĻ þþƷŷƬ | 26uuuþ|