??xml version="1.0" encoding="utf-8" standalone="yes"?>久久夜色精品国产欧美乱,久久99精品久久久久久久不卡,久久久久久久女国产乱让韩http://m.shnenglu.com/zliner/category/1641.html技术学?/description>zh-cnMon, 19 May 2008 17:50:43 GMTMon, 19 May 2008 17:50:43 GMT60用例分析基础http://m.shnenglu.com/zliner/archive/2006/06/01/8038.html依旧的博?/dc:creator>依旧的博?/author>Thu, 01 Jun 2006 09:18:00 GMThttp://m.shnenglu.com/zliner/archive/2006/06/01/8038.htmlhttp://m.shnenglu.com/zliner/comments/8038.htmlhttp://m.shnenglu.com/zliner/archive/2006/06/01/8038.html#Feedback0http://m.shnenglu.com/zliner/comments/commentRss/8038.htmlhttp://m.shnenglu.com/zliner/services/trackbacks/8038.html1. 一个用例可以有多个参与者,q且可以同时有多个参与者?br />用例和参与者的兌可以是双向的Q参与者和用例都可以发起通信?br />
2. 用例之间的基本关pLQ泛化,包含和扩展?br />用例A到B的泛化关p表CA和B是具体与抽象的关pR?br />用例A到B的包含关p表CA使用了B提供的功能?br />用例A到B的扩展关p表CA向B提供的可用的功能?br />但从A到B的包含关pd从B到A的扩展关pL不同的:
A包含B说明B是从A中分解出来的公共行ؓQB自n是独立的Q但对于A来说是不可缺的一部分?br />B扩展A说明B是从A中分解出来的变体行ؓQ必L定扩展点Q也是在基本用例中执行变体行ؓ的具体条件。B仅仅是A的补充,而不是不可缺的部分QB自n也不是独立的。A可以单独执行Q表C通常的情况,在特定的情况下,用B来补充它?br />抽象用例不能被实例化Q不能被实际执行Q它的作用在于更好地l织用例关系?br />



参考书Q?br />《UML用户指南?Grady BoochQJames RumbaughQIvar Jacobson?늻忠等?机械工业出版C?br />《统一软g开发过E?Ivar JacobsonQGrady BoochQJames Rumbaugh?周伯生等?机械工业出版C?br />



]]>
MFC的五U基本机?/title><link>http://m.shnenglu.com/zliner/archive/2006/05/15/7218.html</link><dc:creator>依旧的博?/dc:creator><author>依旧的博?/author><pubDate>Mon, 15 May 2006 11:33:00 GMT</pubDate><guid>http://m.shnenglu.com/zliner/archive/2006/05/15/7218.html</guid><wfw:comment>http://m.shnenglu.com/zliner/comments/7218.html</wfw:comment><comments>http://m.shnenglu.com/zliner/archive/2006/05/15/7218.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/zliner/comments/commentRss/7218.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/zliner/services/trackbacks/7218.html</trackback:ping><description><![CDATA[<p>我们知道MFC的作用在于封装Windows的编E接口,q提供应用程序框架的开发模式。ؓ了完成从前者到后者的q渡QMFC实现了几U基本机Ӟ它们是消息映,命o传递,q行时类信息(RTCI)Q动态创建和序列化?br><br>消息映射和命令传递是对SDKE序交互机制的封装。序列化是应用程序需要的一U基本特性,x数据保存到磁盘和从磁盘打开数据。通过RTCI和动态创建,可以把Y件的对象数据保存到磁盘,反过来从q些数据识别和恢复对象,从而实现对象的序列化。基于数据库的序列化机制和这U方式不同,应用E序和数据库之间有一个约定,以什么样的格式保存什么样的数据,再以同样的方式打开Qƈ且如何重建对象数据也定下来了Q在打开数据Ӟ应用E序不需要有适应性,不需要识别数据类型,也不需要根据在q行期才定的类型名U创建其对象?/p> <p>动态创建就是创建某U类型的对象Q具体类型在q行时确定,~译时可能不知道。比如运行时用户输入一个类型名Uͼ如果该类型是E序cd体系中的一员,则程序中能够创cd的对象。下面的代码是用MFC动态创建机制的一个简化的例子Q?/p> <p>CRuntimeClass* g_pFirstClass;<br>void func()<br>{<br>     char szClassName[64];<br>     CRuntimeClass* pClass;<br>     CObject* pObject;<br>     <br>     cout << "enter a class name...  ";<br>     cin >> szClassName;<br>     <br>     for (pClass = g_pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)<br>     {<br>          if (strcmp(szClassName, pClass->m_lpszClassName) == 0)<br>              pObject = pClass->CreateObject();<br>     }<br>}</p> <p>实现动态创建的思\是把动态的cd名称与程序类型体pM的每一个进行比较,与某个类型吻合时让该cd创徏自n的对象。这P支持动态创建的cd中的每一个类都要额外实现一些功能,卛_别一个名U是否与自n相符Q以及创w的对象?/p> <p>判别一个名U是否与自n相符Q这是运行时c识别的内容Q所以MFC动态创建是在RTCI基础上实现的?/p> <p>RTCI是一个对象能够判定自己是否属于某U类型,该类型的名称在运行时定Q编译时可能不知道。从下面的例子很Ҏ理解RTCIQ?/p> <p>void Func()<br>{<br>     char szClassName[64];<br>     CDocument* pDoc = new CDocument;<br>     <br>     cout << "enter a class name...  ";<br>     cin >> szClassName;<br>     <br>     cout << pDoc->IsKindOf(szClassName); //是返?Q否q回0<br>}</p> <p>有一炚w要说明的是,因ؓCDocumentz于CObjectQ所以IsKindOf对于CObject也要q回1。因为我们是从动态创建出发的Q所以如果是q样可能会有一点背d街但是RTCI明显和动态创建有密切联系QRTCI也可能有单独的h|所以先把RTCI实现h?/p> <p>实现RTCI的思\是让每一个类记录自n的类型信息,q提供IsKindOf(char*)函数q行所l类型与自ncd的比较,而且q要能访问基cȝcd信息Q进行比较,一直到根类。所以记录的cd信息要按l承关系qv来,每个cȝIsKindOf()q要调用基类的IsKindOf()。MFC把要记录的类型信息抽取到一个CRuntimeClassl构体中Q每个类中加入一个CRuntimeClass成员卛_?/p> <p>现在回到动态创建,在RTCI建立的数据结构基上将可实现它。动态创Z不同于IsKindOf()的角度用这一数据l构Q它要遍历所有类型的CRuntimeClass。那么仅仅有l承关系的类的CRuntimeClass相连q不够,要把所有类的CRuntimeClassq成一个链表。其实动态创建ƈ不关心类间的l承关系Q它q等看待每个cR现在以CRuntimeClass为结Ҏ成一个纵横两个方向的链表QIsKindOf()和动态创建分别用它不同的侧面?/p> <p>序列化的概念是在文g中存储对象信息,q能Ҏ它恢复对象。对于文档视囄构的软gQ用户需要保存所~辑的文档和打开已编辑的文档Q这正是序列化的应用Q所以序列化是非帔R要的一U特性。在序列化恢复对象时Q就可以用到动态创建?/p> <p>使用MFC序列化的例子如下Q?/p> <p>void CMyDocument::Serialize(CArichive &ar)<br>{<br>    if (ar.IsStoring())<br>    {<br>        ar << m_pMyClass; //CMyClass m_pMyClass;<br>    }<br>    else<br>    {<br>        ar >> m_pMyClass;<br>    }<br>}</p> <p>一个支持序列化的类提供Serialize(CArchive &)函数Q重?lt;<?gt;>操作。注意两者是不同的,在上例中QCMyDocumentcȝ信息q不被序列化Q而CMyClasscȝ信息被序列化。实际上一个序列化cȝ<<?gt;>操作Q其不涉及类信息的部分是调用Serialize()完成的,它必d时实现这两者?/p> <p>按照MFC的要求,需要在支持序列化的cd义中使用DECLARE_SERIAL宏,在类实现中用IMPLEMENT_SERIAL宏。我们看一下这两个宏实C什么,</p> <p>#define DECLARE_SERIAL(class_name) \<br> _DECLARE_DYNCREATE(class_name) \<br> AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);</p> <p>#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \<br> CObject* PASCAL class_name::CreateObject() \<br>  { return new class_name; } \<br> _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, \<br>  class_name::CreateObject) \<br> AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); \<br> CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) \<br>  { pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \<br>   return ar; } \</p> <p>主要是加入了?gt;>的重载,但是没有重蝲<<QMFC仅提供了CObject?lt;<的重载,如下Q?/p> <p>_AFX_INLINE CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb)<br> { ar.WriteObject(pOb); return ar; }</p> <p>q是因ؓ在序列化d写的时候,都需要具体类的CRuntimeClass信息。相应的GetRuntimeClass()是一个虚函数QCObject重蝲<<Q在写类信息时调用到该函敎ͼ׃虚函数机Ӟ写入的是具体cȝ信息。但是这里隐含着一个条Ӟ是调用<<和GetRuntimeClass()Ӟ具体cd象已l存在了Q而调?gt;>和读入类信息Ӟ该类对象q未被创建,所以无法利用这U机Ӟ只能在每个具体类中都重蝲一?gt;>。我觉得《深入解析MFC》对q个问题的解释不正确?/p> <p>q里有一个问题需要明一下,序列化ؓ什么要写入cM息?一是它应该保存完整的能够独立恢复对象的信息Q二是在E序d对象Ӟ要把它的cM息和E序中期望的(所能处理的)cM息相比较Q进行检验?/p> <p>看IMPLEMENT_SERIAL宏对重蝲>>的实玎ͼ是提供一个期望的CRuntimeClassl构(用于?Q委托CArchiveq行对象d。因对象旉先要跟文件打交道Q所以交lCArchive处理Q随后把d的数据写入对象时QCArchive再调用具体类的Serialize()Q如此合作是十分恰当的。在q里QCArchiveq负责了d和检验类信息Q然后创建对象的q程。因Z斚w具体cd象还不存在,另一斚wq些操作Ҏ有具体类都没有分别,应该提出来,在类U别实现或者让合作者实现。实际上QMFC先把q个q程交给CArchive::ReadClass()Q后者又调用CRuntimeClass::Load()?nbsp;</p> <p>对于序列化来_搞清它的概念以后Q就是实现Serialzie()Q重?lt;<?gt;>。对<<?gt;>的重载涉及很多工作,MFC已经帮我们实CQ我们也看见了大概的设计Q主要是与CArchive分工合作Q其ơ是CRuntimeClass?/p> <p>现在看到CRuntimeClassl构体在MFC对RTCIQ动态创建和序列化的实现中都L重要的作用,重新认识一下这个数据结构很有必要?/p> <p>CRuntimeClass包含了关于类的各U信息和有关操作。把cd其基cȝCRuntimeClassq成一个链表,可以很方便地实现RTCI的IsKindOf()Q把所有类的CRuntimeClassq成一个链表,再加上一个简单的CreateObject函数Q就可以对以Lcdq行动态创建的企图做出反应QCRuntimeClassq实C向文件读写类信息的Load()QStore()Q配合序列化的实现?/p> <p>在分析消息映和命o传递机制之前,需要对<a title=WindowsE序模型 href="http://m.shnenglu.com/zliner/archive/2007/04/15/21942.html">WindowsE序模型</a>有很好的理解?/p> <p>未完待箋...<br><br><br>参考:<br><br>《深入解析MFC?中国电力出版C?br>《深入浅出MFC?华中U大出版C?br>《WindowsE序设计?北大出版C?/p> <img src ="http://m.shnenglu.com/zliner/aggbug/7218.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/zliner/" target="_blank">依旧的博?/a> 2006-05-15 19:33 <a href="http://m.shnenglu.com/zliner/archive/2006/05/15/7218.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>思\ƣ赏http://m.shnenglu.com/zliner/archive/2006/05/12/7045.html依旧的博?/dc:creator>依旧的博?/author>Fri, 12 May 2006 15:14:00 GMThttp://m.shnenglu.com/zliner/archive/2006/05/12/7045.htmlhttp://m.shnenglu.com/zliner/comments/7045.htmlhttp://m.shnenglu.com/zliner/archive/2006/05/12/7045.html#Feedback2http://m.shnenglu.com/zliner/comments/commentRss/7045.htmlhttp://m.shnenglu.com/zliner/services/trackbacks/7045.html
1. 问题Q对32位的二进制整敎ͼ不用循环Q求出其?的个数?br />
#define POW(c) (1<<(c))
#define MASK(c) (((unsigned long)-1) / (POW(POW(c)) + 1))
#define ROUND(n, c) (((n) & MASK(c)) + ((n) >> POW(c) & MASK(c)))

int bit_count(unsigned int n)
{
    n 
= ROUND(n, 0);
    n 
= ROUND(n, 1);
    n 
= ROUND(n, 2);
    n 
= ROUND(n, 3);
    n 
= ROUND(n, 4);
    
return n;
}

基本的想法是把所有的1加v来,得到的就?的个数。我们需要把q些1分离出来Q每?都是q等的,与其位置无关。难题在于不能一个一个去取,那就用到了@环,当然递归也是不允许的。需要有一U统一的办法,可是很难惌具体该怎样。我们逐步地做qg事,假设?6位和?6位分别求得了1的个敎ͼ那么加v来就行了?6位二q制中的1仍然是未知的Q随机出现的Q问题的性质没有变,但我们可以l分解,q种逐步的做法不一定就意味着递归。每?6位分解ؓ两个8位,...,每个2位分解ؓ两个1位,把两?位上的数相加是q两位上1的个数。现在需要取出每一位上的数吗?如果惛_了这个问题,q最l的思\不远了。现?2位已l分成了16个两位,很容易将其看作两?6位,一个是所有奇CQ一个是所有偶C。我们不难把q两?6位分开Q然后移位相加,求Z每两位中1的个数。到了这一步,以后的思\很自然了?br />

参考:

《计二q制?1'的个数》来自?a >http://kaikai.cnblogs.com

]]>
几种排序Ҏ的实?/title><link>http://m.shnenglu.com/zliner/archive/2006/05/09/6825.html</link><dc:creator>依旧的博?/dc:creator><author>依旧的博?/author><pubDate>Tue, 09 May 2006 08:37:00 GMT</pubDate><guid>http://m.shnenglu.com/zliner/archive/2006/05/09/6825.html</guid><wfw:comment>http://m.shnenglu.com/zliner/comments/6825.html</wfw:comment><comments>http://m.shnenglu.com/zliner/archive/2006/05/09/6825.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/zliner/comments/commentRss/6825.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/zliner/services/trackbacks/6825.html</trackback:ping><description><![CDATA[ <div>1. 冒排序<br /><br /> 思想Q?br /><br /></div> <ol> <li>从现有元素中取出最大的元素Q移到相应的位置Q直到所有元素都׃? </li> <li>通过比较和交换逐步调整现有序列Q最l找出最大元素ƈ使其׃?</li> </ol> <p> 设计Q?br /><br /></p> <p>  输入是待排数l及光度,输出排序后的数组?br />  在冒泡过E中Ҏl的有序情况q行查,在数l已l有序时便结束算法?br /><br />代码Q?br /><br />void BubbleSort(int nArray[], int nLength)<br />{<br />     bool bSorted = false;<br />    <br />     if (nArray == NULL)<br />         throw -1;<br />    <br />     if (nLength < 2)<br />         return;<br />    <br />    for (int i = nLength; !bSorted && i > 1; i--)<br />    {<br />         bSorted = true;<br />        <br />         for (int j = 1; j < i; j++)<br />        {<br />             if (nArray[j] < nArray[j-1])<br />            {<br />                 int n;<br />                 n = nArray[j];<br />                 nArray[j] = nArray[j-1];<br />                 nArray[j-1] = n;<br />        <br />                 bSorted = false;<br />             }//if<br />         }<br />     }<br /><br />}<br /><br />2. 双向冒排序<br /><br />void BiBubbleSort(int nArray[], int nLength)<br />{<br />    int  low, high;<br /> <br />    if (nArray == NULL)<br />       throw -1;</p> <p>    if (nLength < 2)<br />       returnt;</p> <p>    low = 0;<br />    high = nLength - 1;<br />    while (low < high)<br />   {<br />       int t;</p> <p>       t = low;<br />       for (int i = low; i < high; i++)<br />       {<br />           if (nArray[i] > nArray[i+1])<br />          {<br />              int n;<br />              n = nArray[i];<br />              nArray[i] = nArray[i+1];<br />              nArray[i+1] = n;<br /><br />              t = i + 1;<br />          }<br />       }<br />       high = t - 1;</p> <p>      t = high;<br />      for (int j = high; j > low; j--)<br />      {<br />          if (nArray[j] < nArray[j-1])<br />          {<br />             int n;<br />             n = nArray[j];<br />             nArray[j] = nArray[j-1];<br />             nArray[j-1] = n;<br />            <br />             t = j - 1;<br />          }<br />      }</p> <p>     low = t + 1;</p> <p>  }//while<br /><br />}<br /><br />3. 快速排?br /><br /> 思想Q?br /><br /> 选一个枢轴元素,把待排序列划分成两段Q前一D不大于枢uQ 后一D不于枢u。如果这两段分别有序Q原序列也随之有序。通过划分Q一个段的排序可以{化ؓ两个子段的排序,卛_h质但较规模的问题。当D늚长度?Ӟ本n是有序的Q{化可以终止?br /><br />设计Q?br /><br />用一个递归函数来实现快速排序算法,递归l止条g是段的长度小于等??br />一ơ划分过E设计如下:取段的第一个元素ؓ枢uQ从最后一个元素向前与枢u比较Q发现小于枢轴的元素Ӟ与枢轴交换位|,从第二个元素向后与枢轴比较,q样两端是已完成划分的部分,中间是待划分的部分,枢u始终处于中间部分的一端,比较从另一端向该端q行Q发现分cM同的元素同枢u交换。随着比较和交换的q行Q中间部分不断收~?每次长度~短1)Q当收羃到长度ؓ1Ӟ划分l止?br /><br />实现要点Q?br /><br />递归函数的参数是待排序列及前后边界?br />划分q程需要用两个变量记录中间部分的边界?br /><br />代码Q?br /><br />void QuickSort(int nArray[], int low, int high)<br />{<br />     int pivot = nArray[low];<br />     int i = lowQj = high;<br />    <br />     if (high < low)<br />           return;   <br />    <br />     while (i < j)<br />     {<br />          while (i < j && nArray[j] >= pivot) j--;<br />          if (i < j) <br />               nArray[i++] = nArray[j];<br /> <br />          while (i < j && nArray[i] <= pivot) i++;<br />          if (i < j) <br />               nArray[j--] = nArray[i];<br />     }<br />    <br />     nArray[i] = pivot;<br />    <br />     QuickSort(nArray, low, i - 1);<br />     QuickSort(nArray, i + 1, high);<br />}<br /><br />试要点Q?</p> <ol> <li>递归l止条g。必Lhigh < lowQ而不能是 high == low。递归的终止是很重要的边界情况Q在实现之前有一个概念上的终止条Ӟ但在实现时处理必d。终止条件和递推方式有关Q需要结合实际的递推方式来确定? </li> <li>递归的递推方式? </li> <li>分划的终止条件。分划过E在i == j时终止,虽然在比较的q程中可能进行交换,但是每次未分划部分的长度?Q用该长度控制分划的l止? </li> <li>分划q程中改变方向时的交接?</li> </ol> <p>法分析Q?br /><br />假设原序列有2<sup>n</sup>个元素,每次分划把一个段{分成两D,则经qnU递归法l止Q每一U递归的比较L为n, 所以QuickSort()的时间ؓO(nlog(n))Q这是^均情c当原序列本w有序时QQuickSort()出现最坏情况,旉为O(n<sup>2</sup>)?/p> <img src ="http://m.shnenglu.com/zliner/aggbug/6825.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/zliner/" target="_blank">依旧的博?/a> 2006-05-09 16:37 <a href="http://m.shnenglu.com/zliner/archive/2006/05/09/6825.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线E通信的机?/title><link>http://m.shnenglu.com/zliner/archive/2006/05/05/6630.html</link><dc:creator>依旧的博?/dc:creator><author>依旧的博?/author><pubDate>Thu, 04 May 2006 16:15:00 GMT</pubDate><guid>http://m.shnenglu.com/zliner/archive/2006/05/05/6630.html</guid><wfw:comment>http://m.shnenglu.com/zliner/comments/6630.html</wfw:comment><comments>http://m.shnenglu.com/zliner/archive/2006/05/05/6630.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/zliner/comments/commentRss/6630.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/zliner/services/trackbacks/6630.html</trackback:ping><description><![CDATA[最原始的多U程通信机制是全局变量Q但是两个线E对同一变量的ƈ发操作可能是冲突的,所谓冲H是指一Uƈ发调度不{h于Q何串行调度。可以通过特定的系l调用保证线E对全局变量的操作具有原子性。这时全局变量成ؓ一U可用的通信机制Q根据通信的需要设计通信的协议,两个U程分别执行Q就可以完成合作。比如辅U程重复某个q程直到ȝE通知它终止,可以U定全局变量为特定值时辅线E终止,让辅U程在@环中全局变量Q主U程讄全局变量通知辅线E终止。这U机制的~点是接攉知的一方必M断检全局变量Q事件机制由此进行了改进。接收方可以在事件上dQ等待特定的通知Q等待的旉可以讑֮Q如果设?Q则事g退化ؓ全局变量。事件只有两U状态,有信h无信Pq相对全局变量是一个限制。事件实C单向的消息,q是最基本的机制。在实际通信zd中还有许多同步问题,每一方不但根据特定的消息采取相应的动作,q在收到消息后发出反馈消息。通信是一个交互和持箋的过E。界段机制是为此而提供的。界段的局限是只有两种状态:锁定和解锁,在很多的通信中,需要进一步量化的状态,q就产生了信号量机制?img src ="http://m.shnenglu.com/zliner/aggbug/6630.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/zliner/" target="_blank">依旧的博?/a> 2006-05-05 00:15 <a href="http://m.shnenglu.com/zliner/archive/2006/05/05/6630.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COM基本概念和COM模型http://m.shnenglu.com/zliner/archive/2006/05/03/6601.html依旧的博?/dc:creator>依旧的博?/author>Wed, 03 May 2006 13:54:00 GMThttp://m.shnenglu.com/zliner/archive/2006/05/03/6601.htmlhttp://m.shnenglu.com/zliner/comments/6601.htmlhttp://m.shnenglu.com/zliner/archive/2006/05/03/6601.html#Feedback0http://m.shnenglu.com/zliner/comments/commentRss/6601.htmlhttp://m.shnenglu.com/zliner/services/trackbacks/6601.html1. 接口

接口是一l函数的集合(更一般情况下Q是一l函数和变量的集?Q对象和客户(E序的两个不同部?可通过它进行通信。接口有特定的内存结构,一个接口指针指向一个虚?vtbl)指针Q虚表是一个函数指针的数组Q每Ҏ向一个接口函数?br />
接口是概忉|的E序元素Q它hl承和多态性。承性是指子接口l承了基接口的所有函敎ͼ子接口可以{型ؓ基接口。在实现上,子接口的虚表包括了基接口的虚表,子接口的虚表指针可以转型为基接口的虚表指针。多态性是指一个基接口的不同子接口可以有不同的行ؓ?br />
2. COM接口(lg模型Ҏ口的要求)

COM作ؓ一U二q制lg模型Q要求对象和客户可能分,它们的一切联p都通过接口q行。一个对象可以有多个接口Q那么,客户在获得第一个接口指针后Q应当可以从一个接口指针查询下一个接口指针,以保持对象的使用。客户应当可以通过接口理对象的生命期Q以l束对象的用。作ZU设计,COM规定从对象的一个接口可以查询它的所有接口,对象生命期管理的责Q分散到每个接?只要客户为每个接口进行生命期理Q就可以实现对象的生命期理)。在实现上,COM接口查询和生命期管理的责Q集中C个IUnknown接口Q所有接口都从IUnknownz。COM接口是从IUnknownz的接口?/p>

2. COM的面向对象特?/p>COM在二q制上提供了一UY件结构模型,q且带有面向对象的特征?br />

  1. COM对象是有状态的Q数据和操作装在一赗COM接口和普通API函数的不同,在于COM对象是有状态的。比如一个宇宙飞船对?实现IMotion接口QIMotion包含void Fly(double dTime)和double GetPosition()函数)Q让它飞行一D|?通过IMotion接口调用Fly()函数)以后它的位置改变了(在飞行前后调用GetPosition()得到不同l果)?/p>

  2. 多?

    同样的接口可以由不同的COM对象实现Q客L序用l一的方法进行处理,却可以得C同的l果。接口也可以zQ不同的子接口对基接口的函数有不同的实现?/p>

    在这里解释一下MFC实现COM对象的机制。一个COM对象可以实现多个接口Q而这些接口都是IUnknown的子接口Q它们对QueryInterface(),  AddRef(),  Release()各有一份实C码,而在同一对象内,q三个函数的内容完全相同Q因此可以抽出来Q委z该对象。又׃对Q何COM对象QAddRef()和Release()的实现本质上也相同,因此可以q一步,抽取q两个函数及其操作的数据(m_Ref)Q放到CCmdTarget中去。QueryInterface()的情冉|所不同Q它操作的数据是依赖于具体COM对象的接口映表Q可以在把函数放qCCmdTarget的同Ӟ实现一个返回接口映表的虚函数QQueryInterface()调用此函数获得具体的接口映射表?/p>

  3. 重用

    COM对象可以用包容和聚合两种方式重用已有的COM对象?/p>

    聚合方式实现重用比较复杂?br />
    在实现对象聚合时Q要解决的一个主要问题是在接口查询上对用户保持透明。客户从暴露出来的内部对象接口进行查询,应当查到的是外部对象的接口。那么收到查询时Q内部对象的IUnknown应当d托外部对象的IUnknown。但是内部对象也可能不被用于聚合Q应该有一个正常的IUnknown。这样可以考虑把内部对象最初收到查询的IUnknown设成一个代理,它根据聚合与否把查询h转交l外部对象IUnknown或内部对象的正常IUnknownQ即内部对象实现两个IUnknownQ作Z理的委托IUnknown和正常的非委托IUnknown。内部对象还要知道外部对象IUnknownQƈ且能判别自n是否被聚合。可以在创徏内部对象时把外部对象IUnknown指针传给它,不是聚合时传递一个空指针Q这样内部对象就得到了够信息?/p>

    引用计数的管理也是一P内部对象的委托IUnknown区别被聚合与否,调用外部对象IUnknown或自w的非委托IUnknown?/p>

    当然Q从外部对象接口要能查到内部对象接口。外部对象需要知道内部对象的IUnknownQ以查询所要暴露给客户E序的接口。这个IUnknown应当是内部对象的非委托IUnknown?/p>



]]>
排序的方?/title><link>http://m.shnenglu.com/zliner/archive/2006/05/03/6595.html</link><dc:creator>依旧的博?/dc:creator><author>依旧的博?/author><pubDate>Wed, 03 May 2006 09:40:00 GMT</pubDate><guid>http://m.shnenglu.com/zliner/archive/2006/05/03/6595.html</guid><wfw:comment>http://m.shnenglu.com/zliner/comments/6595.html</wfw:comment><comments>http://m.shnenglu.com/zliner/archive/2006/05/03/6595.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/zliner/comments/commentRss/6595.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/zliner/services/trackbacks/6595.html</trackback:ping><description><![CDATA[如果有一个随机排列的整数表,怎样它排序呢?q是生活中也l常到的问题。比如给一l牌排序Q我们通常会怎样做呢Q?br /><br />不断从原序列中取出元素来排成一个新序列Q在新序列Ş成的时候保证它有序Q这是插入排序的办法。插入排序需要有I间存放和操作新序列Q这可以在原序列的空间中满。插入排序需要大量的比较和移动,量是O(n*n)。我们也可以每次从现有元素中取出最元素,q样新序列排下来自然是有序的Q这是选择排序的办法。选择排序需要O(n*n)的比较,最坏最好情况下都一栗这是一个缺点,和与之对U的插入排序比较Q选择排序对原序列的情늼乏适应性,冒排序是对此的改进。冒泡排序也基本使用原序列的I间Q每ơ在现有元素中进行比较以L最元素,q过交换逐步把它Ud相应位置。冒泡排序在原序列的基础上逐步调整得到新序列,它可以更加适应原序列的情况Q在最好情况下旉为O(n)。这三种排序是最基本的,其它Ҏ都是从各U角度对它们q行改进?br /><br />三种基本排序都着g从原序列形成新序列的q程。这是最基本的,但还可以把整个过E用分治或渐q的思想来处理。具体的改进Ҏ有多U,希尔排序Q快速排序,归ƈ排序{等Q我们现在可以欣赏它们的思想Q但是当初每U方法的发现都是重要的成果,需要对排序问题有扎实的认识Q也需要创造的灉|?br /><br />希尔排序把原序列分组Q每一l进行插入排序,从较的分组开始逐渐扩大Q直到整个序列作Zl。分l元素是间隔选取的,较小的分l排序完成后Q整个序列就在一个较大的度上有序了Q随着分组的扩大,序列在越来越的度上有序,直到完全有序。希排序利用插入排序对乐观情况的适应性,自顶向下渐进处理Q避免了直接在小度上进行处理的盲目性?br /><br />归ƈ排序反映ZU自底向上的分治思想Q其旉为O(n*log(n))?br /><br />快速排序采用了自顶向下的分L想Q其做法和归q排序有某种对称性?br /><br />基数排序也是自顶向下的分L想Q它从关键字本n衡量问题的解决程度?br /><br /><br /><img src ="http://m.shnenglu.com/zliner/aggbug/6595.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/zliner/" target="_blank">依旧的博?/a> 2006-05-03 17:40 <a href="http://m.shnenglu.com/zliner/archive/2006/05/03/6595.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库范式及其涵?/title><link>http://m.shnenglu.com/zliner/archive/2006/05/02/6562.html</link><dc:creator>依旧的博?/dc:creator><author>依旧的博?/author><pubDate>Tue, 02 May 2006 09:15:00 GMT</pubDate><guid>http://m.shnenglu.com/zliner/archive/2006/05/02/6562.html</guid><wfw:comment>http://m.shnenglu.com/zliner/comments/6562.html</wfw:comment><comments>http://m.shnenglu.com/zliner/archive/2006/05/02/6562.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/zliner/comments/commentRss/6562.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/zliner/services/trackbacks/6562.html</trackback:ping><description><![CDATA[ <p dir="ltr" style="MARGIN-RIGHT: 0px">2NF以上的范式都是对关系上的依赖q行限制Q其中最重要的是3NF和BCNF?/p> <ul> <li> BCNFQ所有非q_依赖都以键为决定子。一个属性集只有包含了整个的键,才能军_集外的属性? </li> <li>3NFQ其非^凡依赖X->A必须满QX是超键,或者A是主属性?NF比BCNF有所放松Q允许含键不完全的属性集军_集外的属性,但必Ld性? </li> <li>不符?NF的情冉|两种: <ol><li>键的真子集决定非d性,即非d性对键的部分依赖Q? </li><li>既非键也非键的真子集决定非d性,由此可证明Q存在非d性对键的传递依赖?/li></ol>如果一个关pM满2但满?Q称此关pȝ?NF?</li> </ul> <p>2NF?NF的涵义是Q键是关pȝ标识信息Q非d性是附属信息。如果附属信息对标识信息的依赖不够紧密,关系的语义单U性就差,从而容易出现各U更新异常?</p> <p>如果q反2NFQ既存在非主属性对键的部分依赖Q会有什么问题?例如关系模式SCGT(S#,C#,G,TN)QS#是学生号QC#是课E号QG是成l,TN是Q课教师姓名,假设每门译֏有一个教师?S#,C#)是键QC#->TN是非d性对键的部分依赖Q因为它的存在会产生三种更新异常Q?). 不开评教师姓名无法插入Q?). 一门课的所有学生都退选,则Q课教师姓名无法保留;3). 一门课更换教师Ӟ必须寚w该评所有学生进行修攏V非d性对键的部分依赖反映了附属信息和标识信息的缺乏整体一致性,所以会产生以上问题?/p> <p>如果W合2NFQ但q反3NFQ即存在非主属性对键的传递依赖,会有什么问题?例如关系模式SDL(S#,DEPT,LOC)QS#是学生号QDEPT是所在系QLOC是系的办公地Q这里S#是键QS#->DEPTQDEPT-/>S#QDEPT->LOCQLOC传递依赖于S#Q因为它的存在会产生三种更新异常Q?). 如果一个系新成立尚未招生,则无法插入;2). 如果一个系不再招生Q但仍ؓ其他pd课,则现有学生毕业后Q系的信息无法保留;3). 一个系更换办公地时Q必d该系的所有学生进行修攏V非d性对键的传递依赖反映了附属信息和标识信息缺乏直接一致性,所以会产生以上问题。缺乏直接一致不如缺乏整体一致那样严重,所以到?NF才排除?/p> <p>那么BCNF的涵义在哪里呢?<br /><br />2NF?NF对一个关pL式中的非d性加以限Ӟ而忽略键之间的关pR如果一个主属性依赖含键不完全的属性组意味着什么呢Q可以证明,该依赖涉及不止一个键Q其军_子有两种情况Q一U是部分键,一U是含部分键和键外的属性。第一U情况下存在一个键之外的属性对该键的部分依赖;W二U情况下Q取一个不含前qC属性的键,易知存在该属性对该键的传递依赖,即一个键外的属性对该键的传递依赖,排除q两U情况就得到BCNF。ؓ什么要q样做呢Q因为有多个键的情况下,必须照顾每一个键Q如果键之外的属性和该键不能保持整体和直接的一_也可能生更新异常。例如SCZ(S,C,Z)QSQCQZ分别表示街道Q城市,邮编Q关pL式上的依赖集为{SC->Z,Z->C}QSC和SZ都是键。如果插入一个城市的总邮~,必须借助一个街道,删除q个街道Q城市的总邮~也被删除,出现q种情况是因为C与SZ键缺乏整体一致性?br /><br /><br />参考:</p> <p>王能斌《数据库pȝ教程?电子工业出版C?/p> <img src ="http://m.shnenglu.com/zliner/aggbug/6562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/zliner/" target="_blank">依旧的博?/a> 2006-05-02 17:15 <a href="http://m.shnenglu.com/zliner/archive/2006/05/02/6562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/S通信和Winsock~程http://m.shnenglu.com/zliner/archive/2006/05/02/6553.html依旧的博?/dc:creator>依旧的博?/author>Tue, 02 May 2006 04:46:00 GMThttp://m.shnenglu.com/zliner/archive/2006/05/02/6553.htmlhttp://m.shnenglu.com/zliner/comments/6553.htmlhttp://m.shnenglu.com/zliner/archive/2006/05/02/6553.html#Feedback0http://m.shnenglu.com/zliner/comments/commentRss/6553.htmlhttp://m.shnenglu.com/zliner/services/trackbacks/6553.html

1. 客户-服务器通信中的基本问题

客户和服务器通信是ؓ了用服务,为此在传输机制的基础上设计协议,通过寚w信行ؓ的规范,实现通信的目的,q解决传输中的问题?/p>

传输机制通常׃层协议提供,Ҏ不同的通信需要选择不同的下层协议,q是一个基本的问题。对应用协议来说Q可用的传输机制有可靠连接的字节类型和不可靠无q接的数据报cd?/p>

服务器处理大量客LhQ从而ƈ发是服务器的一个基本问题,如何处理q个问题也取决于通信需要。处理方式上Q服务器可以是@环的或ƈ发的Qƈ发服务器有多U实现方?异步I/OQ多U程和多q程)?/p>

一件事情能无重复地q箋q行Q通常会获得更好的效率Q这要求M始终知道当前的状态。一ơ通信q程的连l性取决于通信双方Q它们都要知道通信q行的状态。这对客户一般不成问题,但服务器要和大量客户通信Q不一定能为每个客L每次通信保存状态。如果服务器是有状态的Q那么就更快地计响应,减少通信的数据量。但是传输和客户的故障有状态服务器面很大问题Q当传输不可?报文重复Q丢失,乱序)Ӟ服务器维护的状态会和客户失M_一个不断崩溃重启的客户会造成状态信息不能发挥作用,而维护开销却极大增加?/p>

q就提出了客?服务器通信中的三个基本问题Q它们的解决Ҏ都取决于实际需要,客户-服务器通信中有哪些情况的需要呢Q?/p>

  • 是否要求可靠传输Q?
  • 是否需要服务器q行大量处理。对循环服务器进行分析可以知道,需要大量处理的通信用@环方案可能会丢失hQ用q发Ҏq可以提高服务器资源利用率,改善性能Q只要少量处理的通信则无法忍受开销大的解决Ҏ?
  • 在局域网q是互联|环境下Q局域网中传输很出错,互联|环境则不然Q?


通常Ҏ前两个基本问题把服务器实现分为四U类型,它们的适用范围如下Q?/p>

  • 循环无连接服务器Q少量处理的通信Ӟq且在局域网中或不要求可靠传输。这U做法主要是Z避免开销?
  • 循环q接服务器,较少用,主要是@环的方式不够高效Q因接有一定开销Q响应时间可能不低。在量处理q要求可靠性的情况下用?
  • q发无连接服务器Q很用Q因l每个请求开U程Q开销太大。在不要求可靠性的情况下,如果U程开销q小于计响应开销Q或者ƈ发可以让各请求的I/Oq行Q或者@环方案会丢失h时可以考虑?
  • q发q接服务器,常用?


2. winsock基本函数的?/p>

winsock的基本函数有WSAStartup()QWSACleanup()Qsocket()Qclosesocket()Qbind()Qlisten()Qaccept()Q?connect()Qsend()和recv()?/p>

使用q些函数Q客L的大概算法是Q?/p>

  1.  调用WSAStartup()初始化winsock库?
  2.  调用socket()创徏套接字,q回套接字描q符s?
  3.  指定q程套接字地址saQ对s调用connect()Q向sa标识的服务进E请求连接?
  4.  q接成功后,对s调用send()发送请求,调用recv()接收响应Q如此反复直到完成Q务?
  5.  对s调用closesocket()关闭q接?
  6.  不再发vq接处理新的dӞ调用WSACleanup()释放winsock库?

服务器端的大概算法是Q?/p>

  1. 调用WSAStartup()初始化winsock库?
  2. 调用socket()创徏套接字,q回套接字描q符s?
  3. 对s调用bind()Q将其绑定到本地的套接字sa?
  4. 调用listen()Q将s|ؓ被动模式。此时开始侦听客L的连接请求,其攑օ一个队列?
  5. 对s调用accept()Q即从请求队列中取出一,接受该连接后q回一个新的套接字描述Ws'Q以及对应客L的套接字地址sa'?
  6. 对s'调用recv()接收hQ调用send()发送响应,如此反复直到完成d?
  7. 对s'调用closesocket()关闭该连接?
  8. 重复5?的过E?
  9. ?退出后Q调用WSACleanup()释放winsock库?

有以下几炚w要进一步说明,

1). 客户端调用connect()和服务器端调用accept()成功后将在客戯E和服务器进E之间徏立一个TCPq接。连接两端的每个套接字描q符都包含一个本地端点地址和一个远E端点地址。所以在使用q接套接字发送数据时不用指示目的地址?/p>

2). 多宿M机的IP地址选择问题。从上面的算法容易提L问题Qؓ什么客L在用套接字时不l定端点地址Q通常的主机只有一个IPQ但是多宿主L有多个IP地址Q在q种情况下,客户端ؓ套接字指定的IP可能与实际发送时l过的IP不符Q所以允许客L不指定套接字地址Q而由TCP/IP软g在实际发送时指定IPQ同旉择一个未用过的端口号Q这正是在connect()调用中完成的。那么服务器端就不存在同L情况吗?不是Q在它调用bind()时指定一个套接字地址Q其端口部分采用应用协议的熟知端口,而IP地址部分有着同样的问题。ؓ此定义了一个代表统配地址的常量INADDR_ANYQ用它指CIP地址部分。实际用的IP仍然是由TCP/IP软g分配?/p>

3). TCPZ个连接的发送端和接收端各维护一个缓冲区。当发送端~冲区满的时候,send()调用会阻塞,在接收端~冲ZؓI的时候,recv()调用会阻塞。ؓ什么要在通信q程和TCPq接之间l护一个间接层呢?可能是ؓ了在一端有多个q程要用信道的情况下,在多个进E之间进行信道分配的协调。比如在发送端Q信道传输数据时send()调用可以l箋执行Q多个进E的send()调用同缓冲区打交道,彼此影响不大Q因写缓冲区速度很快Q而信道同~冲区打交道Q这时可以对各进E的发送数据进行协调,实现公^的信道分配。另外,在TCP中有滑动H口概念Q是用于量控制的,前述~冲区和滑动H口有什么关p?我现在不太清楚?/p>

4). 套接字的关闭问题。在客户机和服务器通过TCPq接完成数据交换后,有一个安全关闭的问题。一斚wQ服务器不能关闭q接Q因为客h可能q有hQ另一斚wQ客h虽然知道何时不再hQ但是它不知道服务器的响应何时发送完Q因为有些应用协议的响应数据量不定。ؓ此采用部分关闭的办法Q虽然连接是双向的,但是允许在一个方向上关闭它,当客L不再hӞ可以部分关闭q接Q服务器收C个信P如果响应发送完了,服务器就可以关闭q接Q此时连接被完全关闭

3. 套接字接口中的端点地址

端点地址用来表示通信的进E,是传输层协议及其套接字接口中的重要概c不同的协议族可以用不同方式表示端点地址Q一个协议族q可以有多个地址族,每个地址族的地址格式不同。TCP/IP只有一个地址族,它的端点地址包括一?2位IP地址和一?6位端口号。在协议族和地址族的基础上,套接字接口用更ؓ具体的结构来表示端点地址?/p>

套接字是一U适用于多个协议族的接口,q允怸个协议族使用多个地址族。TCP/IP协议族及其唯一地址族的标识分别是PF_INET和AF_INET。由于套接字接口的通用性,它提供一个通用的地址l构Q其格式?地址族,该族中的套接字地址)。套接字作ؓ一个接口标准,可以有不同实玎ͼ以下我们只讨论windows套接字?/p>

如下定义的sockaddr实现了前q通用地址l构Q?/p>

// winsock2.h

struct sockaddr {
        u_short sa_family;              /* address family */
        char    sa_data[14];            /* up to 14 bytes of direct address */
};

sockaddr的通用性是相对的,某些地址族不适合q个l构?/p>

管sockaddr适合于TCP/IP协议族,但是winsockq定义了TCP/IP专用的地址格式Q?/p>

// winsock2.h

struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};

sin_family域取值恒为AF_INET。其中的in_addrl构表示IP地址Q定义如下,

//winsock2.h

struct in_addr {
        union {
                struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { u_short s_w1,s_w2; } S_un_w;
                u_long S_addr;
        } S_un;
#define s_addr  S_un.S_addr
                                /* can be used for most TCP & IP code */
#define s_host  S_un.S_un_b.s_b2
                                /* host on imp */
#define s_net   S_un.S_un_b.s_b1
                                /* network */
#define s_imp   S_un.S_un_w.s_w2
                                /* imp */
#define s_impno S_un.S_un_b.s_b4
                                /* imp # */
#define s_lh    S_un.S_un_b.s_b3
                                /* logical host */
};

Z保证软g的可UL性与可维护性,讉KTCP/IP的代码不应用sockaddr。只使用TCP/IP的应用程序可以只使用sockaddr_inQ而永q不用sockaddr?/p>

4. winsockE序实例

《vc6技术内q》的例程ex34a包括一个web服务器和三个客户Q服务器用winsock实现Q一个客LwinsockQ另两个用wininet。我们以winsock实现的服务器和客户ؓ例?/p>

CBlockingSocket对各接口函数q行装Q它们的调用可以统一报错。把错误查和函数调用一起封装可以避免每ơ调用这些函数时都检错。ؓl一报错Q采用了异常机制Q在出错误后抛出异常Q然后统一q行异常处理。异常机制我们可以把错误检查和错误处理分开Q检查必L分散的,但是处理可以适当集中Q代码化?/p>

CHttpBlockingSocketҎ接收http报文的特点对CBlockingSocketq行了扩展。成员函数ReadHttpHeaderLine()可以从TCPq接中按行接收字W?它引入了一个缓冲区Q缓冲区中收到的字符构成一行后再输出。该~冲区的长度需要能够容Ux一行字W,溢出时报错。接收输的缓冲区也可能长度不Iq时接收的数据不一行,在调用ReadHttpHeaderLine()时要注意q一?QReadHttpResponse()用于接收首部行之后所有的响应Q当调用者提供的~冲Zx会报错。缓冲区不的情况都是在CBlockingSocket::Receive()函数中检到的,该函数调用以上层ơ中的代码按照正常情늼写?/p>

CSockAddr是一个与sockaddr_in同样用途的c,但是用法更方ѝwinsock函数使用的端点地址l构是sockaddrQsockaddr_in本n用来代替它,所以CSockAddr需要能够替代sockaddr。sockaddr可能用在传值或传址参数中,CSockAddr必须在逻辑上和存储上都和sockaddr有等h,q实现有兛_制类型{换。CSockAddrq实C和sockaddr, sockaddr_in互相转换的成员函敎ͼ因ؓ一U结构很隑֜所有情况下都好用,新结构也需要和旧结构保持兼宏V?br>

 

本例中采用服务器关闭套接字的办法Q因为每ơ连接只处理一个请求?br>
参考:

《用TCP/IPq行|际互联W三?windows套接字版)?清华出版C?/p>

《vc6技术内q?5th ed?希望电子出版C?/p>

]]>
论面向对?/title><link>http://m.shnenglu.com/zliner/archive/2006/05/02/6552.html</link><dc:creator>依旧的博?/dc:creator><author>依旧的博?/author><pubDate>Tue, 02 May 2006 04:44:00 GMT</pubDate><guid>http://m.shnenglu.com/zliner/archive/2006/05/02/6552.html</guid><wfw:comment>http://m.shnenglu.com/zliner/comments/6552.html</wfw:comment><comments>http://m.shnenglu.com/zliner/archive/2006/05/02/6552.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/zliner/comments/commentRss/6552.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/zliner/services/trackbacks/6552.html</trackback:ping><description><![CDATA[<p>软g中的对象同领域中的概忉|着密切的关pR?/p> <p>我们知道概念是h们在某个领域中实늻验的ȝQƈ可能发展为理论。概忉|以客观事物ؓ基础Q但不是对客观事物的L反映。它来自于实践,所以包含主体因素,q是很重要的。实跉|概念的根本来源,理论上的需要对概念形成也有一些作用?/p> <p>软g中用的对象cM于领域中使用的概c《UML与模式应用》中_面向对象是按照概念而不是功能进行分解。ؓ什么Y件要使用概念性元素呢Q因Zh的认识是概念性的Q而Y件由人来使用Qh来开发。ؓ了提供有良好概念性的用户接口QY件本w适宜采用概念性元素。由人来开发的软g则更需要采用概忉|元素,软g本n和领域实践都有巨大的复杂性,Z是按照功能性元素来思考的Q面向对象可以让开发h员用概念性元素思考,从而增加对复杂性的适应和控制能力?/p> <p>领域概念是对象的重要来源Q但是对象也形成于Y件开发的q程。一斚wQY件的使用没有改变领域实践的本质,臛_没有完全改变Q而概念反映了领域中已l成熟的认识Q所以是非常重要的指导和参考。另一斚wQ领域实는软gq行和由行确实非怸同,要求q行新的认识QY件本w的需要也会媄响到对象的Ş成?/p> <p>面向对象的基本特征反映着概念的基本特征?/p> <ol> <li>装Q概念不是静态的Q它的属性和操作不可分? <li>通信Q概念不是孤立的Q概늚属性可以其他概忉|成,也可以在属性中引用其他概念Q概늚操作q程中会用到其它的概c? <li>抽象Q从具体概念可以q一步生抽象概c? <li>多态:抽象概念有着多样的具体表现?/li> </ol> <p>Stroustrup的《C++E序设计语言》中_</p> <p>“cd该用于模拟程序员的和应用的世界里的那些概c?..一个概念不会孤立地存在Q它M一些相关的概念共存Qƈ在与相关概念的相互关pM表现出它的大部分力量?..因ؓ我们要用c表C概念,问题变成了如何去表C概念之间的关系。然而,我们无法在程序语a里表qCQ意的关系。即使能q样做,我们也未必想d它。我们的cd该定义得比日常概忉|H一些——而且也更_?#8221;</p> <p>我们可以体会q段话的深刻性?/p> <ol> <li>cȝ来定义概c首先,概念不是静态的Q它的属性和操作不可分,装是面向对象的W一个特征。然后,概念不是孤立的,一个概忉|L与相x念共存,最基本的关pL两对Q封装和通信Q抽象和多态。前者反映了分工与合作关p,后者反映了抽象与具体关pR类是面向对象的核心Q从探讨cȝ作用出发Q就引出了面向对象的四个基本特征? <li>cL定义的概念不但来自应用领域,也来自程序员引入的东ѝ? <li>“我们无法在程序语a里表qCQ意的关系。即使能q样做,我们也未必想d它?#8221; </li> </ol> <img src ="http://m.shnenglu.com/zliner/aggbug/6552.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/zliner/" target="_blank">依旧的博?/a> 2006-05-02 12:44 <a href="http://m.shnenglu.com/zliner/archive/2006/05/02/6552.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://m.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.20xjj.cn" target="_blank">97Ʒ97þþþþ</a>| <a href="http://www.0309999.cn" target="_blank">ŷպƷþ</a>| <a href="http://www.a1dk.cn" target="_blank">þ޾ƷĻ</a>| <a href="http://www.javaoop.cn" target="_blank">һһþAþۺϾƷ </a>| <a href="http://www.0352quan.cn" target="_blank">þþþAVƬ</a>| <a href="http://www.npoq.cn" target="_blank">˳AVɫۺϾþ</a>| <a href="http://www.lkwg.com.cn" target="_blank">99ƷþþƷһ</a>| <a href="http://www.numxj.cn" target="_blank">þ99Ʒŷ</a>| <a href="http://www.7788797.cn" target="_blank">ŷһþþƷ</a>| <a href="http://www.kingvit.com.cn" target="_blank">Ʒþҹҹ³³</a>| <a href="http://www.u1536.cn" target="_blank">ĻƷѾþ</a>| <a href="http://www.bluecc.com.cn" target="_blank">þɫۺһ</a>| <a href="http://www.quheitou.net.cn" target="_blank">þۺϾþ߾Ʒ </a>| <a href="http://www.52037872.cn" target="_blank">ѾþþƷ99reѾy</a>| <a href="http://www.maishuhua.cn" target="_blank">þþƷwwwˬ</a>| <a href="http://www.37eee.cn" target="_blank">͵͵þþþվ</a>| <a href="http://www.cz27b1.cn" target="_blank">99þѹƷ</a>| <a href="http://www.qp8978.cn" target="_blank">һ97ձ˾þۺӰԺ</a>| <a href="http://www.iido.org.cn" target="_blank">þùƷ77777</a>| <a href="http://www.338z.cn" target="_blank">ɫԭһþۺ</a>| <a href="http://www.iview-inc.com.cn" target="_blank">69Ʒþþþ99</a>| <a href="http://www.kwk9605.cn" target="_blank">99þѹƷ</a>| <a href="http://www.xfpz67.cn" target="_blank">þþƷ99Ʒ</a>| <a href="http://www.szmpp.cn" target="_blank">˾Ʒþ޸岻 </a>| <a href="http://www.djdnx.cn" target="_blank">þۺ97ɫֱ</a>| <a href="http://www.sunwebs.cn" target="_blank">wwwþþcom</a>| <a href="http://www.createclouds.cn" target="_blank">þۺϾƷþ</a>| <a href="http://www.baby-photo.com.cn" target="_blank">뾫Ʒþþ</a>| <a href="http://www.enkids.cn" target="_blank">AVþþƷݺݰ˳</a>| <a href="http://www.78cbg.cn" target="_blank">þþ뾫Ʒպý </a>| <a href="http://www.gfba.cn" target="_blank">þҹɫƷŷ</a>| <a href="http://www.fm935.cn" target="_blank">㽶þþþþúݺɫ</a>| <a href="http://www.ejtc.cn" target="_blank">þþþþëƬѿ</a>| <a href="http://www.yt-tongyong.cn" target="_blank">ݲݾþþר</a>| <a href="http://www.indmc.cn" target="_blank">ٸ޾þþþþ</a>| <a href="http://www.i501.cn" target="_blank">þWWW˳һƬ</a>| <a href="http://www.zesf.com.cn" target="_blank">ٸþþþþñŪ߳ </a>| <a href="http://www.dg-rx.cn" target="_blank">þþþƷ</a>| <a href="http://www.take-art.cn" target="_blank">ŮдþӰԺ</a>| <a href="http://www.yunpins.cn" target="_blank">þþþþ޾Ʒ</a>| <a href="http://www.t55n3z.cn" target="_blank">ɫۺϾþۺ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>