??xml version="1.0" encoding="utf-8" standalone="yes"?>日韩一区二区久久久久久,久久亚洲av无码精品浪潮,91精品国产综合久久久久久http://www.shnenglu.com/Lee/category/7130.htmlBeyond C++zh-cnSun, 03 May 2009 15:17:31 GMTSun, 03 May 2009 15:17:31 GMT60C++ 注册表操作ȝhttp://www.shnenglu.com/Lee/archive/2009/05/03/81775.htmlDavid LeeDavid LeeSun, 03 May 2009 09:30:00 GMThttp://www.shnenglu.com/Lee/archive/2009/05/03/81775.htmlhttp://www.shnenglu.com/Lee/comments/81775.htmlhttp://www.shnenglu.com/Lee/archive/2009/05/03/81775.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/81775.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/81775.html
1、RegCloseKey()
  原型QRegCloseKey(HKEY hKey)

  解释Q关闭指定的注册表键Q释攑֏柄。当对一个或多个键或值操作完成以后,需要关闭其键来q行保存操作l果Q关闭一个键后,句柄变ؓ非法Q此时应释放句柄?/div>
2、RegCreateKeyEx()
  原型QLONG RegCreateKeyEx( HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved,
LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult, LPDWORD lpdwDisposition );

  解释Q打开指定的键或子键。如果要打开的键不存在的话,本函C试图建立它。提供该函数是ؓ了向后兼宏V所有的WIN32应用E序应用函数RegCreateKeyExQ)。 各参数及q回值的含义如下Q?/div>

·hKeyZ键|可以取下面的一些数|HKEY_CLASSES_ROOT、HKEY_CURRENT_CONFIG、  HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USER、HKEY_PERFORMANCE_DATA(WINNT操作pȝ)、HKEY_DYN_DATAQWIN9X操作pȝQ;
·参数lpSubKeyZ个指向以零结字符串的指针Q其中包含将要创建或打开的子键的名称。子键不可以用反斜线Q\Q开始。该参数可以为NULLQ?br />
·参数ReservedZ留|必须讄?Q?br />
·参数lpClassZ个指向包含键cd的字W串。如果该键已l存在,则忽略该参数Q?br />
·参数dwOptions为新创徏的键讄一定的属性。可以取下面的一些数|  REG_OPTION_NON_VOLATILE Q表C新创徏的键Z个非短暂性的键(数据信息保存在文件中Q当pȝ重新启动Ӟ数据信息恢复Q;REG_OPTION_VOLATILEQ表C新创徏的键Z个短暂性的键(数据信息保存在内存中Q,Windows95忽略该数|REG_OPTION_BACKUP_RESTORE 仅在WINNT中支持,可以提供优先U支持;

  ·参数samDesired用来讄寚w讉K的权限,可以取下面的一些数|KEY_CREATE_LINKQ表C准许生成符号键QKEY_CREATE_SUB_KEY 表示准许生成子键QKEY_ENUMERATE_SUB_KEYS 表示准许生成枚D子键QKEY_EXECUTE 表示准许q行L作;KEY_NOTIFY表示准许更换通告Q  KEY_QUERY_VALUE 表示准许查询子键QKEY_ALL_ACCESS 提供完全讉KQ是上面数值的l合Q?br />
  KEY_READ 是下面数值的l合QKEY_QUERY_VALUE、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFYQ  KEY_SET_VALUE 表示准许讄子键的数|KEY_WRITE 是下面数值的l合QKEY_SET_VALUE、KEY_CREATE_SUB_KEYQ?br />·参数lpSecurityAttributesZ个指向SECURITY_ATTRIBUTESl构的指针,定q回的句柄是否被子处理过Eѝ如果该参数为NULLQ则句柄不可以被l承。在WINNT中,该参数可以ؓ新创建的键增加安全的描述Q?br />
  ·参数phkResultZ个指向新创徏或打开的键的句柄的指针Q?br />
  ·参数lpdwDispition指明键是被创是被打开的,可以是下面的一些数|  REG_CREATE_NEW_KEY 表示键先前不存在Q现在被创徏QREG_OPENED_EXISTING_KEY 表示键先前已存在Q现在被打开?br />
  如果该函数调用成功,则返回ERROR_SUCCESS。否则,q回gؓ文gWINERROR.h中定义的一个非零的错误代码Q可以通过讄FORMAT_MESSAGE_FROM_SYSTEM标识调用FormatMessageQ)函数来获取一个对错误的M描述?/div>
3、RegOpenKeyExQ)
  原型QLONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions,
REGSAM samDesired, PHKEY phkResult );

  解释Q打开一个指定的键,q返回打开键的句柄?br />
各参数及q回值的含义如下Q?br />·参数hKey的含义同RegCreateKeyEx函数中的hKey参数Q?br />
·参数lpSubKeyZ个指向以零结字符串的指针Q其中包含子键的名称Q可以利用反斜线Q\Q分隔不同的子键名。如果字W串为空Q则ҎhKey参数创徏一个新的句柄。在q种情况下,q不关闭先前打开的句柄;
·参数ulOption保留Q通常必须讄?Q?br />
·参数samDesired的含义同RegCreateKeyEx函数中的samDesired参数Q?br />
·参数phkResultZ个指针,用来指向打开的键的句柄。可以通过RegCloseKey函数关闭q个句柄Q?br />
·函数的返回值同RegCreateKeyEx函数的返回倹{?/div>
4、查询某一个键|RegQueryValueExQ)

  原型QLONG RegQueryValueEx(HKEY hKey, LPCTSTR lpValueName, LPDWORD pReserved, LPDWORD lpType,
LPBYTE lpData, LPDWORD lpcbData );

  解释Q根据要查询的键的句柄,要返回的查询的数据?br />
  各个参数及返回值的含义如下Q?br />
  ·参数hKey为当前的一个打开的键的句柄,具体数值同RegCreateKeyEx函数的hKey参数Q?br />
  ·参数lpVauleNameZ个指向非I的包含查询值的名称的字W串指针Q?br />
  ·参数lpReserved保留Q必MؓNULLQ?br />
  ·参数lpTypeZ个指向数据类型的指针Q数据类型ؓ下列cd之一QREG_BINARY 二进制数据、REG_DWORD 32位整数、REG_DWORD_LITTLE_ENDIAN littleQendian格式的数据,例如0X12345678以(0X78 0X56 0X34 0X12Q方式保存、REG_DWORD_BIG_ENDIAN bigQendian格式的数据,例如0X12345678以(0X12 0X34 0X56 0X78Q方式保存、REG_EXPAND_SZ 一个包含未扩展环境变量的字W串、REG_LINK 一个Unicodecd的链接、REG_MULIT_SZ 以两个零l尾的字W串、REG_NONE 无类型数倹{REG_RESOURCE_LIST 讑֤驱动资源列表、REG_SZ 一个以零结字符串根据函C用的字符集类型的不同而设|ؓUnicode或ANSIcd的字W串Q?br />
  ·参数lpDataZ个指向保存返回值的变量的指针。如果不需要返回|该参数可以ؓNULLQ?br />
  ·参数lpcbDataZ个指向保存返回值长度的变量的指针。其中长度以字节为单位。如果数据类型ؓREG_SZ、REG_MULTI_SZ或REG_EXPAND_SZQ那么长度也包括l尾的零字符Q只有在参数lpData为NULLӞ参数lpcbData才可以ؓNULLQ返回值同RegCreateKeyEx函数的返回|
 5、RegSetValueExQ)

  原型QLONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, DWORD dwType,
const BYTE *lpData, DWORD cbData);

  解释Q设|注册表中的一个键倹{?br />
  各个参数及返回值的含义如下Q?br />
  ·参数hKey的含义同RegCreateKeyEx函数中的hKey参数Q?br />
  ·参数lpValueNameZ个指向包含值名的字W串指针QReserved保留Q通常必须讄?Q?br />
  ·参数dwType定了设|的值的cd同RegQueryValueKeyEx的lyType参数Q?br />
  ·参数lpDataZ个指向包含数据的~冲区的指针Q?br />
  ·参数cbData以字节ؓ单位Q指定数据的长度Q?br />
  q回值同RegCreateKeyEx函数的返回倹{?/div>
6、RegDeketeKeyQ)

  原型QLONG RegDeleteKeyQHKEY hKeyQLPCTSTR lpSubKEYQ;

  解释Q函数RegDeketeKey删除一个键及所有的子键?br />
  各个参数及返回值的含义如下Q?br />
  ·参数hKey的含义同RegCreateKeyEx函数中的hKey参数Q?br />
  ·参数lpSubKey的含义同RegCreateKeyEx函数中的lpSubKey参数?/div>


David Lee 2009-05-03 17:30 发表评论
]]>局部变量、全局变量、静态变?/title><link>http://www.shnenglu.com/Lee/archive/2009/03/19/77103.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Wed, 18 Mar 2009 23:28:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2009/03/19/77103.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/77103.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2009/03/19/77103.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/77103.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/77103.html</trackback:ping><description><![CDATA[ <p>静态变量的cd说明W是static?静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量,例如外部变量虽属于静态存储方式,但不一定是静态变量,必须?static加以定义后才能成为静态外部变量,或称静态全局变量。对于自动变量,它属于动态存储方式?但是也可以用static定义它ؓ静态自动变量,或称静态局部变量,从而成为静态存储方式?/p> <p>  由此看来Q?一个变量可由staticq行再说明,q改变其原有的存储方式?/p> <p>  1. 静态局部变?/p> <p>  在局部变量的说明前再加上static说明W就构成静态局部变量?/p> <p>  例如Q?/p> <p>  static int a,b;</p> <p>  static float array[5]={1,2,3,4,5}Q?</p> <p>  静态局部变量属于静态存储方式,它具有以下特点:</p> <p>  (1)静态局部变量在函数内定义,但不象自动变量那P当调用时存在,退出函数时消失。静态局部变量始l存在着Q也是说它的生存期为整个源E序?/p> <p>  (2)静态局部变量的生存期虽然ؓ整个源程序,但是其作用域仍与自动变量相同Q即只能在定义该变量的函数内使用该变量。退函数后,管该变量还l箋存在Q但不能使用它?/p> <p>  (3)允许Ҏ造类静态局部量赋初倹{若未赋以初|则由pȝ自动赋以0倹{?/p> <p>  (4)对基本类型的静态局部变量若在说明时未赋以初|则系l自动赋?倹{而对自动变量不赋初|则其值是不定的?Ҏ静态局部变量的特点Q?可以看出它是一U生存期为整个源E序的量。虽然离开定义它的函数后不能用,但如再次调用定义它的函数Ӟ它又可l用,而且保存了前ơ被调用后留下的倹{?因此Q当多次调用一个函C要求在调用之间保留某些变量的值时Q可考虑采用静态局部变量。虽然用全局变量也可以达Cq目的,但全局变量有时会造成意外的副作用Q因此仍以采用局部静态变量ؓ?/p> <p>  2.静态全局变量</p> <p>  全局变量(外部变量)的说明之前再冠以static 构成了静态的全局变量。全局变量本n是静态存储方式, 静态全局变量当然也是静态存储方式?q两者在存储方式上ƈ无不同。这两者的区别虽在于非静态全局变量的作用域是整个源E序Q当一个源E序由多个源文gl成Ӟ非静态的全局变量在各个源文g中都是有效的?而静态全局变量则限制了其作用域Q?卛_在定义该变量的源文g内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文g内,只能源文件内的函数公用,因此可以避免在其它源文g中引起错误。从以上分析可以看出Q?把局部变量改变ؓ静态变量后是改变了它的存储方式x变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的用范围。因此static q个说明W在不同的地ҎL作用是不同的。应予以注意?/p> <p>  静态变?/p> <p>  除范围之外,变量q有存活期,在这一期间变量能够保持它们的倹{在应用E序的存zL内一直保持模块变量和公用变量的倹{但是,对于 Dim 声明的局部变量以及声明局部变量的q程Q仅当过E在执行时这些局部变量才存在。通常Q当一个过E执行完毕,它的局部变量的值就已经不存在,而且变量所占据的内存也被释放。当下一ơ执行该q程Ӟ它的所有局部变量将重新初始化?/p> <p>  但可局部变量定义成静态的Q从而保留变量的倹{在q程内部?Static 关键字声明一个或多个变量Q其用法?Dim 语句完全一P</p> <p>  Static Depth</p> <p>  例如Q下面的函数存储在静态变?Accumulate 中的以前的运营dg一个新值相加,以计运营d{?/p> <p>  Function RunningTotal (num)</p> <p>  Static ApplesSold</p> <p>  ApplesSold = ApplesSold + num</p> <p>  RunningTotal = ApplesSold</p> <p>  End Function</p> <p>  如果?Dim 而不?Static 声明 ApplesSoldQ则以前的篏计g会通过调用函数保留下来Q函数只会简单地q回调用它的那个相同倹{?/p> <p>  在模块的声明D声?ApplesSoldQƈ使它成ؓ模块U变量,由此也会收到同样效果。但是,q种Ҏ一旦改变变量的范围Q过E就不再对变量排他性存取。由于其它过E也可以讉K和改变变量的|所以运营dg怸可靠Q代码将更难于维护?/p> <p>  声明所有的局部变量ؓ静态变?/p> <p>  Z使过E中所有的局部变量ؓ静态变量,可在q程头的起始处加?Static 关键字。例如:</p> <p>  Static Function RunningTotal (num)</p> <p>  q就使过E中的所有局部变量都变ؓ静态,无论它们是用 Static、Dim ?Private 声明的还是隐式声明的。可以将 Static 攑֜M Sub ?Funtion q程头的前面Q包括事件过E和声明?Private 的过E?/p> <p> <br />文章出处QDIY部落(<a >http://www.diybl.com/course/3_program/vc/vc_js/20090215/155523.html</a>)</p> <img src ="http://www.shnenglu.com/Lee/aggbug/77103.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2009-03-19 07:28 <a href="http://www.shnenglu.com/Lee/archive/2009/03/19/77103.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++中static的作?/title><link>http://www.shnenglu.com/Lee/archive/2009/03/19/77101.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Wed, 18 Mar 2009 22:36:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2009/03/19/77101.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/77101.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2009/03/19/77101.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/77101.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/77101.html</trackback:ping><description><![CDATA[ <p>   1、什么是static?<br />       static 是C++中很常用的修饰符Q它被用来控制变量的存储方式和可见性?/p> <p>    2、ؓ什么要引入static?<br />       函数内部定义的变量,在程序执行到它的定义处时Q编译器为它在栈上分配空_大家知道Q函数在栈上分配的空间在此函数执行结束时会释放掉Q这样就产生了一 个问? 如果惛_函数中此变量的g存至下一ơ调用时Q如何实玎ͼ 最Ҏ惛_的方法是定义一个全局的变量,但定义ؓ一个全局变量有许多缺点,最明显的缺Ҏ破坏了此变量的访问范_使得在此函数中定义的变量Q不仅仅受此 函数控制Q?/p> <p>    3、什么时候用static?<br />       需要一个数据对象ؓ整个c而非某个对象服务,同时又力求不破坏cȝ装?卌求此成员隐藏在类的内部,对外不可见?/p> <p>    4、static的内部机Ӟ<br />       静态数据成员要在程序一开始运行时必d在。因为函数在E序q行中被调用Q所以静态数据成员不能在M函数内分配空间和初始化?br />       q样Q它的空间分配有三个可能的地方,一是作为类的外部接口的头文Ӟ那里有类声明Q二是类定义的内部实玎ͼ那里有类的成员函数定义;三是应用E序的mainQ)函数前的全局数据声明和定义处?br />      静态数据成员要实际地分配空_故不能在cȝ声明中定义(只能声明数据成员Q。类声明只声明一个类的“尺寸和规格”,q不q行实际的内存分配,所以在cd 明中写成定义是错误的。它也不能在头文件中cd明的外部定义Q因为那会造成在多个用该cȝ源文件中Q对光复定义?br />      static被引入以告知~译器,变量存储在E序的静态存储区而非栈上I间Q静?br />数据成员按定义出现的先后序依次初始化,注意静态成员嵌套时Q要保证所嵌套的成员已l初始化了。消除时的顺序是初始化的反顺序?/p> <p>    5、static的优势:<br />       可以节省内存Q因为它是所有对象所公有的,因此Q对多个对象来说Q静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一P但它?值是可以更新的。只要对静态数据成员的值更Cơ,保证所有对象存取更新后的相同的|q样可以提高旉效率?/p> <p>    6、引用静态数据成员时Q采用如下格式:<br />         <cd>::<静态成员名><br />    如果静态数据成员的讉K权限允许的话(即public的成?Q可在程序中Q按上述格式<br />来引用静态数据成员?/p> <p>    7、注意事:<br />      (1)cȝ静态成员函数是属于整个c而非cȝ对象Q所以它没有this指针Q这导?br />了它仅能讉Kcȝ静态数据和静态成员函数?br />      (2)不能静态成员函数定义ؓ虚函数?br />      (3)׃静态成员声明于cMQ操作于其外Q所以对其取地址操作Q就多少有些Ҏ<br />Q变量地址是指向其数据cd的指?Q函数地址cd是一个“nonmember函数指针”?/p> <p>      (4)׃静态成员函数没有this指针Q所以就差不多等同于nonmember函数Q结果就<br />产生了一个意想不到的好处Q成Z个callback函数Q得我们得以将C++和C-based X W<br />indowpȝl合Q同时也成功的应用于U程函数w上?br />      (5)staticq没有增加程序的时空开销Q相反她q羃短了子类对父c静态成员的讉K<br />旉Q节省了子类的内存空间?br />      (6)静态数据成员在<定义或说?gt;时前面加关键字static?br />      (7)静态数据成员是静态存储的Q所以必d它进行初始化?br />      (8)静态成员初始化与一般数据成员初始化不同:<br />       初始化在cM外进行,而前面不加staticQ以免与一般静态变量或对象相؜淆;<br />       初始化时不加该成员的讉K权限控制WprivateQpublic{;<br />           初始化时使用作用域运符来标明它所属类Q?br />           所以我们得出静态数据成员初始化的格式:<br />         <数据cd><cd>::<静态数据成员名>=<?gt;<br />      (9)Z防止父类的媄响,可以在子cd义一个与父类相同的静态变量,以屏蔽父cȝ影响。这里有一炚w要注意:我们说静态成员ؓ父类和子cd享,但我们有 重复定义了静态成员,q会不会引v错误呢?不会Q我们的~译器采用了一U绝妙的手法Qname-mangling 用以生成唯一的标志?/p> <p> </p> <p> <strong>静态数据成?br /><br /></strong>  在类中,静态成员可以实现多个对象之间的数据׃nQƈ且用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是cȝ所有对象中׃n的成员,而不是某个对象的成员?br /><br />使用静态数据成员可以节省内存,因ؓ它是所有对象所公有的,因此Q对多个对象来说Q静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个 对象都是一P但它的值是可以更新的。只要对静态数据成员的值更Cơ,保证所有对象存取更新后的相同的|q样可以提高旉效率?br /><br />静态数据成员的使用Ҏ和注意事如下:<br /><br />1、静态数据成员在定义或说明时前面加关键字static?br /><br />2、静态成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下:<br /><br /><数据cd><cd>::<静态数据成员名>=<?gt;<br /><br />q表明:<br /><br />        (1) 初始化在cM外进行,而前面不加staticQ以免与一般静态变量或对象相؜淆?br /><br />(2) 初始化时不加该成员的讉K权限控制WprivateQpublic{?br /><br />(3) 初始化时使用作用域运符来标明它所属类Q因此,静态数据成员是cȝ成员Q而不是对象的成员?br /><br />3、静态数据成员是静态存储的Q它是静态生存期Q必d它进行初始化?br /><br />4、引用静态数据成员时Q采用如下格式:<br /><br /><cd>::<静态成员名><br /><br />如果静态数据成员的讉K权限允许的话(即public的成?Q可在程序中Q按上述格式来引用静态数据成员?/p> <p> <strong>静态成员函?br /><br /></strong>  静态成员函数和静态数据成员一P它们都属于类的静态成员,它们都不是对象成员。因此,寚w态成员的引用不需要用对象名?br /><br />在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用cM说明的静态成员。如果静态成员函C要引用非静态成员时Q可通过对象来引用?/p> <p> <br />下面看一个例子:<br />#include <iostream.h><br />class Point<br />{<br />public:<br />void output()<br />{<br />}<br />static void init()<br />{  <br />} <br />};<br />void main( void )<br />{<br />Point pt;<br />pt.init();<br />pt.output(); <br />}<br />q样~译是不会有M错误的?br />下面q样?br />#include <iostream.h><br />class Point<br />{<br />public:<br />void output()<br />{  <br />}<br />static void init()<br />{  <br />} <br />};<br />void main( void )<br />{<br />Point::output();<br />}<br />q样~译会处错,错误信息Q?a name="baidusnap0"></a><strong style="COLOR: black; BACKGROUND-COLOR: rgb(255,255,102)">illegal</strong><a name="baidusnap1"></a><strong style="COLOR: black; BACKGROUND-COLOR: rgb(160,255,255)">call</strong><a name="baidusnap2"></a><strong style="COLOR: black; BACKGROUND-COLOR: rgb(153,255,153)">of</strong><a name="baidusnap3"></a><strong style="COLOR: black; BACKGROUND-COLOR: rgb(255,153,153)">non-static</strong><a name="baidusnap6"></a><strong style="COLOR: white; BACKGROUND-COLOR: rgb(0,170,0)">member</strong><a name="baidusnap7"></a><strong style="COLOR: white; BACKGROUND-COLOR: rgb(136,104,0)">function</strong>Qؓ什么?<br />因ؓ在没有实例化一个类的具体对象时Q类是没有被分配内存I间的?br />好的再看看下面的例子:<br />#include <iostream.h><br />class Point<br />{<br />public:<br />void output()<br />{  <br />}<br />static void init()<br />{  <br />} <br />};<br />void main( void )<br />{<br />Point::init();<br />}<br />q时~译׃会有错误Q因为在cȝ定义Ӟ它静态数据和成员函数有了它的内存区Q它不属于类的Q何一个具体对象?br />好的再看看下面的例子:<br />#include <iostream.h><br />class Point<br />{<br />public:<br />void output()<br />{  <br />}<br />static void init()<br />{ <br />   x = 0;<br />   y = 0;<br />}<br />private:<br />int x;<br />int y;<br />};<br />void main( void )<br />{<br />Point::init();<br />}<br />~译出错Q?br /><strong style="COLOR: black; BACKGROUND-COLOR: rgb(255,255,102)">illegal</strong> reference to data <strong style="COLOR: white; BACKGROUND-COLOR: rgb(0,170,0)">member</strong> 'Point::x' in a static <strong style="COLOR: white; BACKGROUND-COLOR: rgb(0,170,0)">member</strong><strong style="COLOR: white; BACKGROUND-COLOR: rgb(136,104,0)">function</strong><br /><strong style="COLOR: black; BACKGROUND-COLOR: rgb(255,255,102)">illegal</strong> reference to data <strong style="COLOR: white; BACKGROUND-COLOR: rgb(0,170,0)">member</strong> 'Point::y' in a static <strong style="COLOR: white; BACKGROUND-COLOR: rgb(0,170,0)">member</strong><strong style="COLOR: white; BACKGROUND-COLOR: rgb(136,104,0)">function</strong><br />在一个静态成员函数里错误的引用了数据成员Q?br />q是那个问题Q静态成员(函数Q,不属于Q何一个具体的对象Q那么在cȝ具体对象声明之前已l有了内存区Q?br />而现在非静态数据成员还没有分配内存I间Q那么这里调用就错误了,好像没有声明一个变量却提前使用它一栗?br />也就是说在静态成员函C不能引用非静态的成员变量?br />好的再看看下面的例子:<br />#include <iostream.h><br />class Point<br />{<br />public:<br />void output()<br />{<br />   x = 0;<br />   y = 0;<br />   init();  <br />}<br />static void init()<br />{</p> <p>}<br />private:<br />int x;<br />int y;<br />};<br />void main( void )<br />{<br />Point::init();<br />}<br />好的Q这样就不会有Q何错误。这最l还是一个内存模型的问题Q?br />M变量在内存中有了自己的空间后Q在其他地方才能被调用,否则׃出错?br />好的再看看下面的例子:<br />#include <iostream.h><br />class Point<br />{<br />public:<br />void output()<br />{ <br />}<br />static void init()<br />{ <br />   x = 0;<br />   y = 0;<br />}<br />private:<br />static int x;<br />static int y;<br />};<br />void main( void )<br />{<br />Point::init();<br />}<br />~译Q?br />Linking...<br />test.obj : error LNK2001: unresolved external symbol "private: static int Point::y" <br />test.obj : error LNK2001: unresolved external symbol "private: static int Point::x" <br />Debug/Test.exe : fatal error LNK1120: 2 unresolved externals<br />执行 link.exe 时出?<br />可以看到~译没有错误Q连接错误,q又是ؓ什么呢Q?br />q是因ؓ静态的成员变量要进行初始化Q可以这P<br />#include <iostream.h>////////////////////////(q段代码q有疑问Qinit()中的x, y 和static 的x ,y 有联pdQ?<br />class Point<br />{<br />public:<br />void output()<br />{ <br />}<br />static void init()<br />{ <br />   x = 0;<br />   y = 0;<br />}<br />private:<br />static int x;<br />static int y;<br />};<br />int Point::x = 0;<br />int Point::y = 0;<br />void main( void )<br />{<br />Point::init();<br />}<br />在静态成员数据变量初始化之后׃会出现编译错误了?br />再看看下面的代码Q?br />#include <iostream.h><br />class Point<br />{<br />public:<br />void output()<br />{ <br />}<br />static void init()<br />{ <br />   x = 0;<br />   y = 0;<br />}<br />private:<br />static int x;<br />static int y;<br />};<br />void main( void )<br />{<br />}<br />~译没有错误Qؓ什么?<br />即他们没有初始化,因ؓ我们没有讉KxQyQ所以编译不会出错。 ?/p> <p> </p> <p> <font size="2">C++会区分两U类型的成员函数Q静态成员函数和非静态成员函数。这两者之间的一个重大区别是Q静态成员函C接受隐含?em>this</em>自变量。所以,它就无法讉K自己cȝ非静态成员?/font> </p> <p> <font size="2">在某些条件下Q比如说在用诸如pthreadQ它不支持类Q此cȝ多线E库Ӟ必M用静态的成员函数Q因为其地址同C语言函数的地址兼容。这U铜限制p使程序员要利用各U解军_法才能够从静态成员函数访问到非静态数据成员?/font> </p> <p> <font size="2">W一个解军_法是声明cȝ所有数据成员都是静态的。运用这U方式的话,静态的成员函数p够直接地讉K它们Q例如:</font> </p> <p> <font size="2"> <font color="#0066ff">class Singleton<br />{<br />public:<br />   static Singleton * instance();<br />private:<br />   Singleton * p;<br />   static Lock lock;<br />};</font> <br /> <br /> </font> <font color="#0066ff" size="2">Singleton * Singleton::instance()<br />{<br />lock.getlock(); <font color="#006600">// fine, lock is static</font><br />if (!p)<br />   p=new Singleton;<br />lock.unlock();<br />return p;<br />} </font> </p> <p> <font size="2">q种解决Ҏ不适用于需要用非静态数据成员的cR?/font> </p> <p> <font size="2">讉K非静态数据成?/font> </p> <p> <font size="2">参照传递给需要考量的对象能够让静态的成员函数讉K到对象的非静态数据:</font> </p> <p> <font color="#0066ff" size="2">class A<br />{<br />public:<br />   static void func(A & obj);<br />   intgetval() const; <font color="#006600">//<strong style="COLOR: black; BACKGROUND-COLOR: rgb(255,153,153)">non-static</strong><strong style="COLOR: white; BACKGROUND-COLOR: rgb(0,170,0)">member</strong><strong style="COLOR: white; BACKGROUND-COLOR: rgb(136,104,0)">function</strong></font><br />private:<br />intval;<br />}; </font> </p> <p> <font size="2">静态成员函数func()会用参?em>obj</em>来访问非静态成?em>val</em>?/font> </p> <p> <font color="#0066ff" size="2">voidA::func(A & obj)<br />{<br />   int n = obj.getval();<br />} </font> </p> <p> <font size="2">一个参照或者指针作为静态成员函数的自变量传递,是在模仿自动传递非静态成员函数里<em>this</em>自变量这一行ؓ?/font> </p> <img src ="http://www.shnenglu.com/Lee/aggbug/77101.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2009-03-19 06:36 <a href="http://www.shnenglu.com/Lee/archive/2009/03/19/77101.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>默认生成的函数和屏蔽它们的方?/title><link>http://www.shnenglu.com/Lee/archive/2009/03/19/77100.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Wed, 18 Mar 2009 21:17:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2009/03/19/77100.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/77100.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2009/03/19/77100.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/77100.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/77100.html</trackback:ping><description><![CDATA[如果你只是声明一个空c,不做M事情的话Q编译器会自动ؓ你生成一个默认构造函数、一个拷贝默认构造函数、一个默认拷贝赋值操作符和一个默认析构函数?font color="#008080"><strong>q些函数只有在第一ơ被调用Ӟ才会别编译器创徏。所有这些函数都是inline和public的?/strong></font><br /><br /><font color="#008080"><strong>默认的析构函数是非虚函数</strong></font>Q除非基cL自己声明的虚析构函数Q?font color="#008080"><strong>而拷贝默认构造函数和默认拯赋值操作符知识是单U将来源对象的每一个非静态成员拷贝到对象目标中(bitwise copyQ?/strong></font><br /><br />其中的默认拷贝赋值操作符只有在生成的代码合法q且有机会证明它有意义存在时才会生成。这p明,<font color="#008080"><strong>如果你打在一个“内含引用成员”或者“内含const成员”的cd支持赋值操作,必d义自q默认拯赋值操作符?/strong></font>因ؓC++本n不允许引用改指不同的对象Q也不允许更改const成员?br /><br />最后一U情况,<font color="#008080"><strong>当基cd自己的默认拷贝赋值操作符声明为privateӞ子类׃会生自q的默认拷贝赋值操作符?/strong></font>因ؓ假如产生了这L默认拯赋值操作符Q它会试着去调用基cȝ默认拯赋值操作符d理基cȝ部分Q不q的是,它没有权利?br /><br />你可以将拯构造函数或默认拯赋值操作符声明为private。这h声明一个成员函敎ͼ阻止了~译器暗自创建的默认版本Q而这些函CؓprivateQ得可以成功阻止h们调用它?br /><br />上面的做法有一个隐患,因ؓc自w的member和friendq是可以调用q些private函数。有一个很刁钻的方法,?font color="#008080"><strong>成员函数声明ؓprivate而且故意不实现它?/strong></font>”,q样既阻止了默认函数的生成,而且如果你试着调用q些函数Q就会得C个链接错误。只声明Q不定义Q链接器报错。甚臛_声明的时候,你连参数也不用写?br /><br />而试着上q的链接器错误提前到~译器也是可以的。我们专门设计一个类Unconpyable?br />--------------------------------------------------------------------<br />class Uncopybale {<br />protected:<br />    Uncopyable() {}<br />    ~Uncopyable() {}<br />private:<br />    Ucopyable(const Uncopyable&)<br />    Uncopyable& operator=(const Uncopyable&)<br />};<br />--------------------------------------------------------------------<br />ZL对象被拷贝,<font color="#008080"><strong>我们唯一需要做的就是承Uncopyable</strong></font>。这些函数的默认生成版本会尝试调用其基类的对应版本,那些调用会被~译器拒l,因ؓ它基cȝ拯函数是private?br /><br />Boost提供的noncopyablecM有类似的功能?br /><br /><font style="BACKGROUND-COLOR: rgb(0,128,128)" color="#ffffff"><strong>忠告Q?br /><br />Z驛_~译器自动提供的技能,可将相应的成员函数声明ؓprivateq且不予实现。用像Uncopyableq样的基cM是一U做法?/strong></font><img src ="http://www.shnenglu.com/Lee/aggbug/77100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2009-03-19 05:17 <a href="http://www.shnenglu.com/Lee/archive/2009/03/19/77100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/C++ 标准~程 ?cd转换http://www.shnenglu.com/Lee/archive/2009/03/09/76028.htmlDavid LeeDavid LeeMon, 09 Mar 2009 13:34:00 GMThttp://www.shnenglu.com/Lee/archive/2009/03/09/76028.htmlhttp://www.shnenglu.com/Lee/comments/76028.htmlhttp://www.shnenglu.com/Lee/archive/2009/03/09/76028.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/76028.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/76028.html 

一、自动类型{?/strong>

    一般来_同一句语句或表达式应该用同一U类型的变量和常量。如果用了多种cd的变量和帔RQ类型؜用)QC 会自动把它们转换成同一U类型。自动类型{换ؓ我们写程序提供了方便Q却也带来了危机。因_心大意而造成的类型؜用也怼DE序q行出错。以下是自动cd转换的基本规则:

    1. 在表辑ּ中,char ?short cd的|无论有符可是无W号Q都会自动{换成 int 或?unsigned intQ如?short 的大和 int 一Punsigned short 可表C的最大值就大于 intQ在q种情况下,unsigned short 被{换成 unsigned intQ。因为它们被转换成表C围更大的cdQ故而我们把q种转换UC为?strong>升Q?font color="#990000">promotionQ”?/p>

    2. 按照从高C的顺序给各种数据cd分等U,依次为:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int ?int。这里有一个小的例外Q如?long ?int 大小相同Q则 unsigned int 的等U应位于 long 之上。char ?short q没有出Cq个{列表Q是因ؓ它们参与q算时就应该已经被升U成?int 或?unsigned int?/p>

    3. 在Q何涉及两U数据类型的操作中,它们之间{较低的类型会被{换成{较高的类型?/p>

    4. 在赋D句中Q? 双的值在赋予 = 左边的变量之前,首先要将双的值的数据cd转换成左边变量的cd。也是_左边变量是什么数据类型,双的值就要{换成什么数据类型的倹{这个过E可能导致右边的值的cd升Q也可能D其类?strong>降Q?font color="#990000">demotionQ。所谓“降U”,是指{较高的类型被转换成等U较低的cd?/p>

    5. 作ؓ参数传递给函数Ӟchar ?short 会被转换?intQfloat 会被转换?double。用函数原型可以避免这U自动升U。这Ҏ以后会详l讲解?/p>

    cd升通常不会有什么问题,但是cd降却会带来不少问题。例如:

        char ch = 1222;

1222 降?charQ但 char 无法表示 1222。再如:

        int j = 22.2;

22.2 降?intQ小数部分被截断?/p>


二、类型{换运符

    使用cd转换q算W可以指定我们想要进行的cd转换。类型{换运符由括号和cd名组成:

        (type)

其中Q我们应该用我们惌{换成的类型替换掉 typeQ例如:(long), (unsigned long)?/p>

    cd转换q算W应该放在值的前面Q?/p>

        int i = (int)1.1 + (int)2.2;

1.1 在加法运前因为类型{换运符而降Uؓ intQ其值变?1。类似地Q?.2 也降Uؓ intQ其值变?2。又如:

        int j = 20;
        double k = (double)j;

j 的D转换?doubleQ然后用于初始化 k?/p>


三、小例子

    #include <stdio.h>

    int main(void)
    {
        char ch;
        int i;
        float fl;
        double db;

        db = fl = i = ch = 'C';                 /* 10 */
        printf("ch=%c, i=%d, fl=%2.2f, db=%2.2f\n", ch, i, fl, db);

        ch = ch + 1;                            /* 13 */
        i = db + fl + 2 * ch;                   /* 14 */
        fl = 2.0 * ch + i;                      /* 15 */
        db = 22 * i + ch - fl;                  /* 16 */
        printf("ch=%c, i=%d, fl=%2.2f, db=%2.2f\n", ch, i, fl, db);

        i = 666.6 + 777.7;                      /* 19 */
        printf("Now i = %d\n", i);
        i = (int)666.6 + (int)777.7;            /* 21 */
        printf("Now i = %d\n", i);

        return 0;
    }

我的pȝ中,char ?8 位的Qint ?32 位的。输ZؓQ?/p>

    ch=C, i=67, fl=67.00, db=67.00
    ch=D, i=270, fl=406.00, db=5602.00
    Now i = 1444
    Now i = 1443

W?10 行,'C' 的D转换?charQ然后赋值给 ch。ch 的D转换?intQ然后赋值给 i。以此类推?/p>

W?13 行,= 双?ch 的值先被{换成 intQ然后和 1 相加Q得?32 位的 int cd整数 68。最后,68 降?charQ然后赋值给 ch。在 ASCII 中,D 的编码是 68?/p>

W?14 行,ch 的D转换?intQ然后和 2 怹?136。fl 的D转换?doubleQ然后和 db 相加Q其和再与{换成 double ?136 相加?270.0 。最后,270.0 被{换成 intQ然后赋值给 i?/p>

W?15 行,ch 的D转换?doubleQ然后和 2.0 怹Qi 的D转换?doubleQ然后和前面得到的乘U相加,相加的得数被转换?floatQ然后赋值给 fl?/p>

W?16 行,22 ?i 怹?5940Qch 的D转换?intQ然后和 5940 相加?6008Q然后,6008 被{换成 floatQ再?fl 相减?5602.0fQ最?5602.0f 被{换成 doubleQ再赋值给 db?/p>

W?19 行,666.6 ?777.7 相加?1444.3Q然?1444.3 被降U成 intQ再赋值给 i?/p>

W?21 行,cd转换q算W把 666.6 ?777.7 转换?intQ得 666 ?777Q它们相加得 1443Q最后,1443 被赋值给 i?/p>

注意Q?font color="#ff0000">cd转换改变的是值的cdQ而不是对象的cdQ对象的cd自始至终都是不变?/font>。例如:

    i = fl + ch;

ch 的D转换?floatQ?ch 本n仍然?char cd的变量?/p>

参考资?/strong>QC Primer 5th Edition
          The C Programming Language 2nd Edition
          C99 标准



David Lee 2009-03-09 21:34 发表评论
]]>
new/delete 和malloc/free 的区别(l合转帖Q?/title><link>http://www.shnenglu.com/Lee/archive/2009/03/09/75990.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Mon, 09 Mar 2009 08:18:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2009/03/09/75990.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/75990.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2009/03/09/75990.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/75990.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/75990.html</trackback:ping><description><![CDATA[ <p> <strong>相同?/strong>Q都可用于申请动态内存和释放内存</p> <p> <strong>不同?/strong>Q?br />(<strong>1)操作对象有所不同</strong>?br />malloc与free是C++/C 语言的标准库函数Qnew/delete 是C++的运符。对于非内部数据cȝ对象而言Q光用maloc/free 无法满动态对象的要求。对象在创徏的同时要自动执行构造函敎ͼ 对象消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运符Q不在编译器控制权限之内Q不能够把执行构造函数和析构函数的Q务强加malloc/free?/p> <p> <strong>(2)在用法上也有所不同</strong>?br />函数malloc 的原型如下:<br /><strong>void * malloc(size_t size);</strong><br />用malloc 甌一块长度ؓlength 的整数类型的内存Q程序如下:<br />int *p = (int *) malloc(sizeof(int) * length);<br />我们应当把注意力集中在两个要素上Q“类型{换”和“sizeof”?br />􀂋 malloc q回值的cd是void *Q所以在调用malloc 时要昑ּ地进行类型{换,void * 转换成所需要的指针cd?br />􀂋 malloc 函数本nq不识别要申L内存是什么类型,它只兛_内存的d节数?/p> <p>函数free 的原型如下:<br /><strong>void free( void * memblock );</strong><br />Z么free 函数不象malloc 函数那样复杂呢?q是因ؓ指针p 的类型以及它所指的内存的容量事先都是知道的Q语句free(p)能正地释放内存。如果p 是NULL 指针Q那么free </p> <p>对p 无论操作多少ơ都不会出问题。如果p 不是NULL 指针Q那么free 对pq箋操作两次׃DE序q行错误?/p> <p> <strong>new/delete 的用要?br /></strong>q算Wnew 使用h要比函数malloc 单得多,例如Q?br />int *p1 = (int *)malloc(sizeof(int) * length);<br />int *p2 = new int[length];<br />q是因ؓnew 内置了sizeof、类型{换和cd安全查功能。对于非内部数据cd的对象而言Qnew 在创建动态对象的同时完成了初始化工作。如果对象有多个构造函敎ͼ那么new 的语句也可以有多UŞ式?/p> <p>如果用new 创徏对象数组Q那么只能用对象的无参数构造函数。例?br />Obj *objects = new Obj[100]; // 创徏100 个动态对?br />不能写成<br />Obj *objects = new Obj[100](1);// 创徏100 个动态对象的同时赋初?<br />在用delete 释放对象数组Ӟ留意不要丢了W号‘[]’。例?br />delete []objects; // 正确的用?br />delete objects; // 错误的用?br />后者相当于delete objects[0]Q漏掉了另外99 个对象?br />/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br /><br /><br />1  new自动计算需要分配的I间Q而malloc需要手工计字节数<br />2  new是类型安全的Q而malloc不是Q比如:<br />int* p = new float[2]; // ~译时指出错?br />int* p = malloc(2*sizeof(float)); // ~译时无法指出错?br />new operator ׃步构成,分别?operator new ?construct<br />3  operator new对应于mallocQ但operator new可以重蝲Q可以自定义内存分配{略Q甚至不做内存分配,甚至分配到非内存讑֤上。而malloc无能为力<br />4  new调用constructorQ而malloc不能Qdelete调用destructorQ而free不能?br />5  malloc/free要库文g支持Qnew/delete则不要?<br />/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br /><br />1. 本质区别<br />malloc/free是C/C++语言的标准库函数Qnew/delete是C++的运符?br />对于用户自定义的对象而言Q用maloc/free无法满动态管理对象的要求。对象在创徏的同时要自动执行构造函敎ͼ对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运符Q不在编译器控制权限之内Q不能够把执行构造函数和析构函数的Q务强加于malloc/free。因此C++需要一个能完成动态内存分配和初始化工作的q算WnewQ以及一个能完成清理与释攑ֆ存工作的q算Wdelete?br /><br /></p> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"> <span style="COLOR: #0000ff">class</span> <span style="COLOR: #000000"> Obj<br />{<br /></span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000"> :<br />      Obj(</span> <span style="COLOR: #000000">) { cout </span> <span style="COLOR: #000000"><<</span> <span style="COLOR: #000000"> “Initialization”?/span> <span style="COLOR: #000000"><<</span> <span style="COLOR: #000000"> endl; }<br />      </span> <span style="COLOR: #000000">~</span> <span style="COLOR: #000000">Obj(</span> <span style="COLOR: #000000">) { cout </span> <span style="COLOR: #000000"><<</span> <span style="COLOR: #000000"> “Destroy”?/span> <span style="COLOR: #000000"><<</span> <span style="COLOR: #000000"> endl; }<br />      </span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000"> Initialize(</span> <span style="COLOR: #000000">) { cout </span> <span style="COLOR: #000000"><<</span> <span style="COLOR: #000000"> “Initialization”?/span> <span style="COLOR: #000000"><<</span> <span style="COLOR: #000000"> endl; }<br />      </span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000"> Destroy(</span> <span style="COLOR: #000000">) { cout </span> <span style="COLOR: #000000"><<</span> <span style="COLOR: #000000"> “Destroy”?/span> <span style="COLOR: #000000"><<</span> <span style="COLOR: #000000"> endl; }<br />};<br /><br /></span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000"> UseMallocFree(</span> <span style="COLOR: #000000">)<br />{<br />      Obj  </span> <span style="COLOR: #000000">*</span> <span style="COLOR: #000000">a </span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000"> (obj </span> <span style="COLOR: #000000">*</span> <span style="COLOR: #000000">) malloc( </span> <span style="COLOR: #0000ff">sizeof</span> <span style="COLOR: #000000">( obj ) );     </span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000"> allocate memory</span> <span style="COLOR: #008000"> <br /> </span> <span style="COLOR: #000000">      a</span> <span style="COLOR: #000000">-></span> <span style="COLOR: #000000">Initialize();                                                </span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000"> initialization<br />      </span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000">?/span> <span style="COLOR: #008000"> <br /> </span> <span style="COLOR: #000000">      a</span> <span style="COLOR: #000000">-></span> <span style="COLOR: #000000">Destroy();   </span> <span style="COLOR: #008000">                                             // deconstruction</span> <span style="COLOR: #008000"> <br /> </span> <span style="COLOR: #000000">      free(a);                                                           <font color="#008000">// release memory<br /></font></span> <span style="COLOR: #000000">}<br /><br /></span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000"> UseNewDelete(</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">)<br />{<br />    Obj  </span> <span style="COLOR: #000000">*</span> <span style="COLOR: #000000">a </span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000"> </span> <span style="COLOR: #0000ff">new</span> <span style="COLOR: #000000"> Obj;  </span> <span style="COLOR: #008000">                                       </span> <span style="COLOR: #008000"> <br />    </span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000">?/span> <span style="COLOR: #008000"> <br /> </span> <span style="COLOR: #000000">    delete a;</span> <span style="COLOR: #008000"> <br /> </span> <span style="COLOR: #000000">}</span> </div> <p> <br />cObj的函数Initialize实现了构造函数的功能Q函数Destroy实现了析构函数的功能。函数UseMallocFree中,׃malloc/free不能执行构造函C析构函数Q必调用成员函数Initialize和Destroy来完成“构造”与“析构”。所以我们不要用malloc/free来完成动态对象的内存理Q应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过E,对它们而言malloc/free和new/delete是等L?br /><br />2. 联系<br />既然new/delete的功能完全覆盖了malloc/freeQؓ什么C++q保留malloc/free呢?因ؓC++E序l常要调用C函数Q而CE序只能用malloc/free理动态内存。如果用free释放“new创徏的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc甌的动态内存”,理论上讲E序不会出错Q但是该E序的可L很差。所以new/deleteQmalloc/free必须配对使用?br />///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br /><br /><br /></p> <img src ="http://www.shnenglu.com/Lee/aggbug/75990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2009-03-09 16:18 <a href="http://www.shnenglu.com/Lee/archive/2009/03/09/75990.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]C++资源之不完全导引Q完整版Q?/title><link>http://www.shnenglu.com/Lee/archive/2009/02/25/74811.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Tue, 24 Feb 2009 16:26:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2009/02/25/74811.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/74811.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2009/02/25/74811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/74811.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/74811.html</trackback:ping><description><![CDATA[ <p>来源Q?a >www.csdn.net</a><br />撰文Q曾毅、陶?br />声明Q本?004q?月首发于《CSDN开发高手》,版权归该杂志与《程序员》杂志社<br />所有?br />------------------------------------------------------------------------<br />  1Q前a</p> <p>  无数ơ听到“我要开始学习C++!”的呐喊Q无数次听到“C++太复杂了Q我真的<br />学不会”的无奈。Stan Lippman先生曑֜《C++ Primer》一书中指出“C++是最为难<br />学的高E序设计语言之一”,Z常将“之一”去掉以表达自己对C++的敬畏。诚<br />ӞC++E序设计语言对于学习者的有很多难以逾越的`沟,体系l构的庞大,?br />接不暇ƈ不断扩充的特性……除此之外,参考资料之多与冗杂使它的学习者望而却<br />步,Ʋ求深入者苦不堪a。希望这一份不完全导引能够成ؓ您C++学习之\上的引\<br />灯?/p> <p>  撰写本文的初衷ƈ不打带领大家体验古老的C++历史Q如果你想了解C++的历<br />史与其前期发展中诸多技术的演变Q你应当d考Bjarne的《The Design and Evo<br />lution of C++》。当然也不打给大家一个无所不包的宝典(q不想Q其一是因<br />水^有限Q其二无奈C++之博大精深)Q所l出的仅仅是一些我们认为对于想学习C<br />++的广大读者来说最重要q且触手可及的开发与学习资源?/p> <p>  本文介绍q分析了一些编译器Q开发环境,库,量的书c以及参考网站,q?br />且尽可能试着l出一个利用这些资源的导引Q望对如同我们一L初学者能够有<br />所裨益?/p> <p>-----------------------------------------------------------------------</p> <p>  2Q编译器</p> <p>  在C++之外的Q何语a中,~译器都从来没有受到q如此之重视。因为C++是一<br />门相当复杂的语言Q所以编译器也难于构建。直到最q我们才开始能够用上完全<br />W合C++标准的编译器Q哦Q你可能会责怪那些编译器厂商不能早的提供符合标?br />的编译器Q这只能怪他们各自维pȝ自n的一套别Z愿接受的标准Q。什么??br />说这无关紧要Q哦Q不Q你所需要的是和标准化C++高度兼容的编译环境。长q来?br />Q只有这L~译器对C++开发h员来说才是最有意义的工具Q尤其是对于E序设计<br />语言的学习者。一x让代码具备可移植性,q让一门语a及其库的应用更ؓq泛<br />。嗯Q是的,我们q里只打介l一些公认的优秀~译器?/p> <p>  2.1 Borland C++</p> <p>  q个是Borland C++ Builder和Borland C++ Builder Xq两U开发环境的后台<br />~译器。(哦,我之所以将之分ZU开发环境你应当能明白ؓ什么,正如Delphi<br />7到Delphi8的{变,是革命性的两代。)Borland C++p牌开发工具厂商Borland<br />們֊打造。该公司的编译器素以速度快,I间效率高著UͼBorland C++ pd~译<br />器秉承了q个传统Q属于非怼质的~译器。标准化斚w早在5.5版本的编译器中对<br />标准化C++的兼容就辑ֈ?2.73%。目前最新版本是Borland C++ Builder X中的6.<br />0版本Q官方称100%W合ANSI/ISO的C++标准以及C99标准。嗯…这正是我前面所指的<br />“完全符合C++标准的编译器”?/p> <p>  2.2 Visual C++</p> <p>  q个正是我们熟知的Visual Studio ?Visual Studio.net 2002, 2003以及2<br />005 Whidbey中带的C++~译器。由Microsoft公司研制。在Visual Studio 6.0中,<br />因ؓ~译器有太多地方不能与后来出现的C++标准相吻合而饱受批评(x你在使用<br />STL的时候编译时报出的那些o人厌恶的error和warning吧)。VC++6.0Ҏ准化C+<br />+的兼容只?3.43%。但是随着C++~译器设计大师Stanley Lippman以及诸多C++C?br />达人的加盟Q在Visual Studio.NET 2003中,Visual C++~译器已l成Z个非<br />常成熟可靠的C++~译器了。Dr.Dobb's Journal的评显CVisual C++7.1Ҏ准C<br />++的兼Ҏ高?8.22%Q一度成为CBX之前兼容性最好的~译器。结合强大的Visua<br />l Studio.NET开发环境,是一个非怸错的选择。至于Whidbey时代的Visual C++,<br />g微Y所最x的是C++/CLI……我们不惌论微软下一代的C++~译器对标准?br />兼容如何Q但他确实越来越适合.NET (其实你和我的感觉可能是一LQ微软不?br />当把标准C++q块肥肉丢给Borland,然而微软可能ƈ不这栯??/p> <p>  2.3 GNU C++</p> <p>  著名的开源C++~译器。是cUnix操作pȝ下编写C++E序的首选。特Ҏ有非<br />常好的移植性,你可以在非常q泛的^C使用它,同时也是~写跨^収ͼ嵌入?br />E序很好的选择。另外在W合标准q个斚w一直都非常好,GCC3.3大概能够辑ֈ96<br />.15%。但是由于其跨^台的Ҏ,在代码尺寔R度{优化上略微差一炏V?/p> <p>  ZGNU C++的编译器有很多,比如Q?/p> <p>  (1) Mingw<br />  <a >http://www.mingw.org/</a><br />  GCC的一个Windows的移植版本(Dev-C++的后収ͼ</p> <p>  (2) Cygwin<br />  <a >http://sources.redhat.com/cygwin/</a><br />  GCC的另外一个WindowsUL版本是Cygwin的一部分QCygwin是Windows下的一?br />Unix仿真环境。严格的说是模拟GNU的环境,q也是"Gnu's Not Unix"要表辄?br />思,噢,扯远了,qƈ不是我们在这里关心的实质内容?/p> <p>  (3) Djgpp<br />  <a >http://www.delorie.com/djgpp/</a><br />  q是GCC的DOSUL版本?/p> <p>  (4) RSXNT<br />  <a >http://www.mathematik.uni-bielefeld.de/~rainer/</a><br />  q是GCC的DOS和WindowsUL版本?/p> <p>  (5) Intel C++<br />  著名CPU刉厂商Intel出品的编译器QSpecial Design for Intel x86Q对?br />Intel x86l构的CPUl过特别的优化。在有些应用情况下,特别是数D等高?br />能应用,仅仅采用Intel的编译器~译p大幅度的提高性能?/p> <p>  (6) Digital Mars C++<br />  |络上提供免费下载,Zortech/Symantec C++的承者,其前w在当年惨烈?br />C++四国战中也是主角之一?/p> <p>  3Q开发环?/p> <p>  开发环境对于程序员的作用不a而喻。选择自己朝夕相处的环境也不是Ҏ?br />事情Q特别是在IDE如此丰富的情况下。下面就是我们推荐的一些常见的C++开发环<br />境,q没有包括一些小型的Q罕见的IDE。其中Q何一N是功能丰富,可以用作?br />常开发用的。对于不同层面的开发者,请参见内文关于适用对象的描q?/p> <p>  3.1 Visual Studio 6.0</p> <p>  q个虽然是Microsoft公司的老版本的开发环境,但是鉴于其后l版本Visual<br />Studio.NET的庞大nw,以及初学者ƈ不那么高的功能要求,所以推荐这个开发环<br />境给C++的初学者,供其学习C++的最基本的部分,比如C的那部分子集Q当然你别指<br />望他能够支持最新的C99标准。在日常的开发中Q仍然有很多公司使用q个l典E_<br />的环境,比如W者就看曾亲见有些公司其~译器替换ؓGCC做手机开发之用?/p> <p>  3.2 Visual Studio.NET 2003</p> <p>  作ؓMicrosoft公司官方正式发布的最新版本开发环境,其中有太多激动h心的<br />功能。结合其最新的C++~译器。对于机器配|比较好的开发h员来_使用q个开<br />发环境将能满_大部分的要求。这里不打算单独说Visual Studio Whidbey,虽然<br />Visual Studio .NET 2005 - WhidbeyC֌预览版已l推出,但暂不是很稳定,读?br />可以亲nM验?/p> <p>  3.3 Borland C++ Builder 6</p> <p>  q个q不是Borland的C++开发环境的最新版本。选择它的原因是它不是用Java<br />写的IDEQ速度比较快。它有一个很完善的GUIH体设计器,和Delphiq一个VCL?br />׃q些特点Q比较适合初学者上手。但是由于其GUI的中心位|,可能不利于对?br />C++语言的学习。而且其ؓ了支持VCLq个Object Pascal写的库也对C++q行了一?br />U有的扩充。得h们有一个不得不接受的事实:“Borland C++ Builder 6的高?br />几乎都是Delphi高手”?/p> <p>  3.4 Borland C++ Builder X</p> <p>  正如前文所qͼ虽然版本号上和前面那个IDE非常相象Q但是其实它们是完全?br />同的两个集成开发环境。C++Builder更多的是一个和Delphi同步的C++版本的开发环<br />境,C++BuilderX则是完全从C++的角度思考得出的一个功能丰富的IDE。其最大的?br />Ҏ跨^収ͼ跨编译器Q多UFramework的集成,q且有一个WxWindows为基的GU<br />I设计器。尤其是采用了纯C++来重写了整个Framework,摒弃了以前o人无奈的版本<br />。对于C++的开发来_从编译器Q到库,到功能集成都是非常理想的。可以预见,<br />Borland C++ Builder X 2.0很值得C++爱好者期待。唯一令h隑֠之处是作Z?br />C++的开发工P其IDE是用Java写的Q在配置不够理想的机器上h重考虑再安?br />?/p> <p>  3.5 Emacs + GCC</p> <p>  前面讲的大部分是Windows环境下的集成开发环境。Linux上的开发者更們֐?br />使用Emacs来编辑C++的文Ӟ用Makefile来命令GCC做编译。虽然看上去比较松散Q?br />但是q些东西l合hq是一个开发环境。如果你能够娴熟的用这L环境写程<br />序,你的水^应该_指导我们来写q篇陋文了?/p> <p>  3.6 Dev C++</p> <p>  GCC是一个很好的~译器。在Windows上的C++~译器一直和标准有着一D距ȝ<br />时候,GCC是一个让Windows下开发者流口水的编译器。Dev-C++是能够让GCC?br />在Windows下的工具Q作为集成开发环境,q提供了同专业IDE相媲的语法高亮Q?br />代码提示Q调试等功能。由于用Delphi开发,占用内存,速度很快Q比较适合<br />轻量U的学习和用?/p> <p>  3.7 Eclipse + CDT</p> <p>  Eclipse可是q来大名鼎鼎的开发工兗最C期的Jolt大奖颁l了q个杰出<br />的神物。说其神奇是因ؓQ它本n是用Java写的Q但是拥有比一般Java写的E序?br />得多的速度。而且因ؓ其基于插件组装一切的原则Q得能够有CDTq样的插件把E<br />clipse变成一个C/C++的开发环境。如果你一直用Eclipse写Java的程序,不妨用它<br />体验一下C++开发的乐趣?/p> <p>  4Q工?/p> <p>  C++的辅助工L多,我们分门别类的ؓ大家作介l:<br />  4.1 文档c?br />  (1) Doxygen<br />  参考站点:<a >http://www.doxygen.org</a><br />  Doxygen是一U适合C风格语言Q如C++、C、IDL、Java甚至包括C#和PHPQ的?br />开放源码的、基于命令行的文档生器?/p> <p>  (2) C++2HTML<br />  参考站点:<a >http://www.bedaux.net/cpp2html/</a><br />  把C++代码变成语法高亮的HTML</p> <p>  (3) CodeColorizer<br />  参考站点:<a >http://www.chami.com/colorizer/</a><br />  它能把好几种语言的源代码着色ؓHTML</p> <p>  (4) Doc-O-Matic<br />  参考站点:<a >http://www.doc-o-matic.com/</a><br />  Doc-O_MaticZ的C/C++QC++.netQDelphi/Pascal, VB.NETQC#和JavaE序<br />或者组件生准的文档。Doc-O-Matic使用源代码中的符号和注释以及外部的文?br />文g创徏与流行的文档样式一致的文档?/p> <p>  (5) DocVizor<br />  参考站点:<a >http://www.ucancode.net/Products/DocBuilder/Features.htm</a><br />  DocVizor满了面向对象Y件开发者的基本要求——它让我们能够看到C++工程<br />中的cdơ结构。DocVizor快速地产生完整可供打印的类层次l构图,包括从第?br />方库中来的那些类Q除此之外DocVizorq能从类信息中生HTML文g?/p> <p>  (6) SourcePublisher C++<br />  参考站点:<a >http://www.scitools.com/sourcepublisher_c.html</a><br />  l源代码产生提供快速直观的HTML报表Q包括代码,cdơ结构,调用和被?br />用树Q包含和被包含树。支持多U操作系l?/p> <p>  (7) Understand<br />  参考站点:<a >http://www.scitools.com/ucpp.html</a><br />  分析M规模的C或者C++工程Q帮助我们更好的理解以及~写文档?/p> <p>  4.2 代码c?br />  (1) CC-Rider<br />  参考站点:<a >http://www.cc-rider.com</a><br />  CC-Rider是用于C/C++E序强大的代码可视化工具Q通过交互式浏览、编辑及?br />动文件来促进E序的维持和发展?/p> <p>  (2) CodeInspect<br />  参考站点:<a >http://www.yokasoft.com/</a><br />  一U新的C/C++代码分析工具。它查我们的源代码找出非标准的,可能的,?br />及普通的错误代码?/p> <p>  (3) CodeWizard<br />  参考站点:<a >http://www.parasoft.com</a><br />  先进的C/C++源代码分析工P使用过500个编码规范自动化地标明危险的Q?br />但是~译器不能检查到的代码结构?/p> <p>  (4) C++ Validation Test Suites<br />  参考站点:<a >http://www.plumhall.com/suites.html</a><br />  一l用于测试编译器和库对于标准dE度的代码库?/p> <p>  (5) CppRefactory<br />  参考站点:<a >http://cpptool.sourceforge.net/</a><br />  CPPRefactory是一个得开发者能够重构他们的C++代码的程序。目的是使得C<br />++代码的重构能够尽可能的有效率和简单?/p> <p>  (6) Lzz<br />  参考站点:<a >http://www.lazycplusplus.com/</a><br />  Lzz是一个自动化许多C++~程中的体力zȝ工具。它能够节省我们许多事gq?br />且得编码更加有乐趣。给Zpd的声明,Lzz会给我们创徏头文件和源文件?/p> <p>  (7) QA C++ Generation 2000<br />  参考站点:<a >http://www.programmingresearch.com/solutions/qacpp.htm</a><br />  它关注面向对象的C++源代码,Ҏ关于设计Q效率,可靠性,可维护性的部分<br />提出警告信息?/p> <p>  (8) s-mail project - Java to C++DOL<br />  参考站点:<a >http://sadlocha.strefa.pl/s-mail/ja2dol.html</a><br />  把Java源代码翻译ؓ相应的C++源代码的命o行工兗?/p> <p>  (9) SNIP from Cleanscape Software International<br />  参考站点:<a >http://www.cleanscape.net/stdprod/snip/index.html</a><br />  一个填q编码和设计之间沟壑的易于用的C++开发工P节省大量~辑和调?br />的事Ӟ它还使得开发者能够指定设计模式作为对象模型,自动从对象模型中产生<br />C++的类?/p> <p>  (10) SourceStyler C++<br />  参考站点:<a >http://www.ochresoftware.com/</a><br />  对C/C++源代码提供完整的格式化和排版控制的工兗提供多?5个的格式化?br />以及完全支持ANSI C++?/p> <p>  4.3 ~译c?br />  (1) Compilercache<br />  参考站点:<a >http://www.erikyyy.de/compilercache/</a><br />  Compilercache是一个对你的C和C++~译器的装脚本。每ơ我们进行编译,?br />装脚本,把编译的l果攑օ~存Q一旦编译相同的东西Q结果将从缓存中取出而不<br />是再ơ编译?/p> <p>  (2) Ccache<br />  参考站点:<a >http://ccache.samba.org/</a><br />  Ccache是一个编译器~存。它使用h像C/C++~译器的~存预处理器Q编?br />速度通常能提高普通编译过E的5~10倍?/p> <p>  (3) Cmm (C++ with MultiMethods)<br />  参考站点:<a >http://www.op59.net/cmm/cmm-0.28/users.html</a><br />  q是一UC++语言的扩展。读入Cmm源代码输出C++的源代码Q功能是对C++语言<br />d了对multimethod的支持?/p> <p>  (4) The Frost Project<br />  参考站点:<a >http://frost.flewid.de/</a><br />  Forst使得你能够在C++E序中像原生的C++Ҏ一样用multimethod以及虚函<br />数参数。它是一个编译器的外壟?/p> <p>  4.4 试和调试类<br />  (1) CPPUnit<br />  CppUnit 是个Z LGPL 的开源项目,最初版本移植自 JUnitQ是一个非怼<br />U的开源测试框架。CppUnit ?JUnit 一样主要思想来源于极限编E。主要功能就<br />是对单元试q行理Qƈ可进行自动化试?/p> <p>  (2) C++Test<br />  参考站点:<a >http://www.parasoft.com/</a><br />  C++ Test是一个单元测试工P它自动化了C和C++c,函数或者组件的试?/p> <p>  (3) Cantata++<br />  参考站点:<a >http://www.iplbath.com/products/tools/pt400.shtml</a><br />  设计的目的是Z满在合理的l济开销下用这个工具可以让开发工E师开<br />展单元测试和集成试的需?</p> <p>  (4) Purify<br />  参考站点:<a >http://www-900.ibm.com/cn/software/rational/products/purif</a><br />yplus/index.shtml<br />  IBM Rational PurifyPlus是一套完整的q行时分析工P旨在提高应用E序?br />可靠性和性能。PurifyPlus内存错误和泄漏、应用程序性能描述、代码覆?br />分析{功能组合在一个单一、完整的工具包中?/p> <p>  (5) BoundsChecker<br />  BoundsChecker是一个C++q行旉误检和调试工具。它通过在Visual Studi<br />o内自动化调试q程加速开发ƈ且羃短上市的周期。BoundsChecker提供清楚Q详l?br />的程序错误分析,许多是对C++独有的ƈ且在staticQstack和heap内存中检和?br />断错误,以及发现内存和资源的泄漏。  <br />        <br />        (6) Insure++<br />  参考站点:<a >http://www.parasoft.com/</a><br />  一个自动化的运行时E序试工具Q检查难以察觉的错误,如内存覆盖,内存?br />漏,内存分配错误Q变量初始化错误Q变量定义冲H,指针错误Q库错误Q逻辑?br />误和法错误{?/p> <p>  (7) GlowCode<br />  参考站点:<a >http://www.glowcode.com/</a><br />  GlowCode包括内存泄漏查,code profilerQ函数调用跟t等功能。给C++开<br />发者提供完整的错误诊断Q和q行时性能分析工具包?/p> <p>  (8) Stack Spy<br />  参考站点:<a >http://www.imperioustech.com/</a><br />  它能捕捉stack corruption, stack over run, stack overflow{有x的错<br />误?/p> <p>  5Q库</p> <p>  在C++中,库的C是非帔R的。C++之父 Bjarne Stroustrup先生多次表示?br />设计库来扩充功能要好q设计更多的语法的言论。现实中QC++的库门类J多Q解?br />的问题也是极其广泛,库从轻量U到重量U的都有。不都是让人眼界大开Q亦?br />是望而生叹的思维C。由于库的数量非常庞大,而且限于W者水qI其中很多q?br />不了解。所以文中所提的一些库都是比较著名的大型库?/p> <p>  5.1 标准?/p> <p>  标准库中提供了C++E序的基本设施。虽然C++标准库随着C++标准折腾了许多年<br />Q直到标准的出台才正式定型,但是在标准库的实C却很令hƣ慰得看到多U实<br />玎ͼq且已被实践证明为有工业U别强度的佳作?/p> <p>  (1) Dinkumware C++ Library<br />  参考站点:<a >http://www.dinkumware.com/</a><br />  P.J. Plauger~写的高品质的标准库。P.J. Plauger博士是Dr. Dobb'sE序?br />计杰出奖的获得者。其~写的库长期被Microsoft采用Qƈ且最qBorland也取得了<br />其OEM的licenseQ在其C/C++的品中采用Dinkumware的库?/p> <p>  (2) RogueWave Standard C++ Library<br />  参考站点:<a >http://www.roguewave.com/</a><br />  q个库在Borland C++ Builder的早期版本中曄被采用,后来被其他的库给?br />换了。笔者不推荐使用?/p> <p>  (3) SGI STL<br />  参考站点:<a >http://www.roguewave.com/</a><br />  SGI公司的C++标准模版库?/p> <p>  (4) STLport<br />  参考站点:<a >http://www.stlport.org/</a><br />  SGI STL库的跨^台可UL版本?/p> <p>  5.2 “准”标准库 - Boost<br />  参考站点:<a >http://www.boost.org</a><br />  国内镜像Q?a >http://www.c-view.org/tech/lib/boost/index.htm</a><br />  Boost库是一个经q千锤百点{可UL、提供源代码的C++库,作ؓ标准库的?br />备,是C++标准化进E的发动Z一?Boost库由C++标准委员会库工作l成员发?br />Q在C++C֌中媄响甚大,其成员已q?000人?Boost库ؓ我们带来了最新、最酗?br />最实用的技术,是不折不扣的“准”标准库?br />  Boost中比较有名气的有q么几个库:</p> <p>  Regex<br />  正则表达式库<br />  Spirit<br />  LL parser frameworkQ用C++代码直接表达EBNF</p> <p>  Graph<br />  囄件和法</p> <p>  Lambda<br />  在调用的地方定义短小匿名的函数对象,很实用的functional功能</p> <p>  concept check<br />  查泛型编E中的concept</p> <p>  Mpl<br />  用模板实现的元编E框?/p> <p>  Thread<br />  可移植的C++多线E库</p> <p>  Python<br />  把C++cd函数映射到Python之中</p> <p>  Pool<br />  内存池管?/p> <p>  smart_ptr<br />  5个智能指针,学习指针必读Q一份不错的参考是来自CUJ的文章:</p> <p>  Smart Pointers in BoostQ哦Q这文章可以查刎ͼCUJ是提供在U浏览的?br />中文版见W者在《Dr. Dobb's Journal软g研发杂志》第7辑上的译文?/p> <p>  BoostM来说是实用h值很高,质量很高的库。ƈ且由于其对跨q_的强调,<br />Ҏ准C++的强调,是编写^台无养ICC++的开发者必备的工具。但是Boost中也<br />有很多是实验性质的东西,在实际的开发中实用需要}慎。ƈ且很多Boost中的库功<br />能堪U对语言功能的扩展,其构造用精巧的手法Q不要N然的p旉研读。Bo<br />ost另外一面,比如Graphq样的库则是h工业强度Q结构良好,非常值得研读?br />_֓代码Qƈ且也可以攑ֿ的在产品代码中多多利用?/p> <p>5.3 GUI</p> <p>  在众多C++的库中,GUI部分的库是比较J荣Q也比较引h注目的。在实际开<br />发中QGUI库的选择也是非常重要的一件事情,下面我们lD一下可选择的GUI库,<br />各自的特点以及相兛_L支持?/p> <p>  (1) MFC</p> <p>  大名鼎鼎的微软基cdQMicrosoft Foundation ClassQ。大凡学qVC++?br />人都应该知道q个库。虽然从技术角度讲QMFC是不大漂亮的Q但是它构徏于Windo<br />ws API 之上Q能够ɽE序员的工作更容?~程效率高,减少了大量在建立 Windo<br />ws E序时必ȝ写的代码Q同时它q提供了所有一?C++ ~程的优点,例如l承<br />和封装。MFC ~写的程序在各个版本的Windows操作pȝ上是可移植的Q例如,?br />Windows 3.1下编写的代码可以很容易地UL?Windows NT ?Windows 95 上。但<br />是在最q发展以及官Ҏ持上日渐势微?/p> <p>  (2) QT</p> <p>  参考网站:<a >http://www.trolltech.com/</a><br />  Qt是Trolltech公司的一个多q_的C++囑Ş用户界面应用E序框架。它提供l?br />应用E序开发者徏立艺术的图形用L面所需的所用功能。Qt是完全面向对象的<br />很容易扩展,q且允许真正地组件编E。自?996q早些时候,Qtq入商业领域Q?br />它已l成为全世界范围内数千种成功的应用程序的基础。Qt也是行的Linux桌面?br />境KDE 的基Q同时它q支持Windows、Macintosh、Unix/X11{多U^台?/p> <p>  (3) WxWindows</p> <p>  参考网站:<a >http://www.wxwindows.org/</a><br />  跨^台的GUI库。因为其cdơ极像MFCQ所以有文章介绍从MFC到WxWindows?br />代码UL以实现跨q_的功能。通过多年的开发也是一个日完善的GUI库,支持?br />样不׃前面两个库。ƈ且是完全开放源代码的。新q的C++ Builder X的GUI设计<br />器就是基于这个库的?/p> <p>  (4) Fox</p> <p>  参考网站:<a >http://www.fox-toolkit.org/</a><br />  开放源代码的GUI库。作者从自己亲n的开发经验中得出了一个理想的GUI库应<br />该是什么样子的感受出发Q从而开始了对这个库的开发。有兴趣的可以尝试一下?/p> <p> <br />  (5) WTL<br />  ZATL的一个库。因Z用了大量ATL的轻量手法Q模板等技术,在代码尺<br />寸,以及速度优化斚w做得非常C。主要面向的使用体是开发COM轻量U供|络<br />下蝲的可视化控g的开发者?/p> <p>  (6) GTK</p> <p>  参考网站:<a >http://gtkmm.sourceforge.net/</a><br />  GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnomeq样的杀手应用?br />而GTK是q个库的C++装版本?/p> <p>  5.4 |络通信</p> <p>  (1) ACE</p> <p>  参考网站:<a >http://www.cs.wustl.edu/~schmidt/ACE.html</a><br />  C++库的代表Q超重量U的|络通信开发框架。ACE自适配通信环境QAdaptive<br />Communication EnvironmentQ是可以自由使用、开放源代码的面向对象框Ӟ?br />其中实现了许多用于ƈ发通信软g的核心模式。ACE提供了一l丰富的可复用C++?br />装外观(Wrapper FacadeQ和框架lgQ可跨越多种q_完成通用的通信软gd<br />Q其中包括:事g多\分离和事件处理器分派、信号处理、服务初始化、进E间?br />信、共享内存管理、消息\由、分布式服务动态(重)配置、ƈ发执行和同步Q等<br />{?/p> <p>  (2) StreamModule</p> <p>  参考网站:<a >http://www.omnifarious.org/StrMod/</a><br />  设计用于化编写分布式E序的库。尝试着使得~写处理异步行ؓ的程序更?br />易,而不是用同步的外壛_起异步的本质?/p> <p>  (3) SimpleSocket</p> <p>  参考网站:<a >http://home.hetnet.nl/~lcbokkers/simsock.htm</a><br />  q个cd让编写基于socket的客?服务器程序更加容易?/p> <p>  (4) A Stream Socket API for C++<br />  参考网站:<a >http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.h</a><br />tml</p> <p>  又一个对Socket的封装库?/p> <p>  5.5 XML</p> <p>  (1) Xerces</p> <p>  参考网站:<a >http://xml.apache.org/xerces-c/</a><br />  Xerces-C++ 是一个非常健壮的XML解析器,它提供了验证Q以及SAX和DOM API<br />。XML验证在文档类型定?Document Type DefinitionQDTD)斚w有很好的支持Q?br />q且?001q?2月增加了支持W3C XML Schema 的基本完整的开放标准?/p> <p>  (2) XMLBooster</p> <p>  参考网站:<a >http://www.xmlbooster.com/</a><br />  q个库通过产生特制的parser的办法极大的提高了XML解析的速度Qƈ且能够<br />生相应的GUIE序来修改这个parser。在DOM和SAX两大LXML解析办法之外提供?br />另外一个可行的解决Ҏ?/p> <p>  (3) Pull Parser</p> <p>  参考网站:<a >http://www.extreme.indiana.edu/xgws/xsoap/xpp/</a><br />  q个库采用pullҎ的parser。在每个SAX的parser底层都有一个pull的parse<br />rQ这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得试?/p> <p> <br />  (4) Xalan</p> <p>  参考网站:<a >http://xml.apache.org/xalan-c/</a><br />  Xalan是一个用于把XML文档转换为HTMLQ纯文本或者其他XMLcd文档的XSLT?br />理器?/p> <p>  (5) CMarkup</p> <p>  参考网站:<a >http://www.firstobject.com/xml.htm</a><br />  q是一U用EDOM的XML解析器。在很多思\上面非常灉|实用。值得大家在D<br />OM和SAX之外L一点灵感?/p> <p>  (6) libxml++</p> <p>  <a >http://libxmlplusplus.sourceforge.net/</a><br />  libxml++是对著名的libxml XML解析器的C++装版本</p> <p>  5.6 U学计算</p> <p>  (1) Blitz++</p> <p>  参考网站:<a >http://www.oonumerics.org/blitz/</a><br />  Blitz++ 是一个高效率的数D函数库Q它的设计目的是希望建立一套既?br />像C++ 一h便,同时又比Fortran速度更快的数D环境。通常Q用C++所写出<br />的数值程序,?Fortran?0%左右Q因此Blitz++正是要改掉这个缺炏V方法是?br />用C++的template技术,E序执行甚至可以比Fortran更快。Blitz++目前仍在发展?br />Q对于常见的SVDQFFTsQQMRES{常见的U性代数方法ƈ不提供,不过使用者可?br />很容易地利用Blitz++所提供的函数来构徏?/p> <p>  (2) POOMA</p> <p>  参考网站:<a >http://www.codesourcery.com/pooma/pooma</a><br />  POOMA是一个免费的高性能的C++库,用于处理q行式科学计。POOMA的面向对<br />象设计方便了快速的E序开发,对ƈ行机器进行了优化以达到最高的效率Q方便在<br />工业和研I环境中使用?/p> <p>  (3) MTL</p> <p>  参考网站:<a >http://www.osl.iu.edu/research/mtl/</a><br />  Matrix Template Library(MTL)是一个高性能的泛型组件库Q提供了各种格式<br />矩阵的大量线性代数方面的功能。在某些应用使用高性能~译器的情况下,比如In<br />tel的编译器Q从产生的汇~代码可以看出其与手写几乎没有两L效能?/p> <p>  (4) CGAL</p> <p>  参考网站:<a >www.cgal.org</a></p> <p>  Computational Geometry Algorithms Library的目的是把在计算几何斚w的大<br />部分重要的解x案和Ҏ以C++库的形式提供l工业和学术界的用户?/p> <p>  5.7 游戏开?/p> <p>  (1) Audio/Video 3D C++ Programming Library</p> <p>  参考网站:<a >http://www.galacticasoftware.com/products/av/</a><br />  AV3D是一个跨q_Q高性能的C++库。主要的Ҏ是提供3D囑ŞQ声效支持(S<br />B,以及S3MQ,控制接口Q键盘,鼠标和遥感)QXMS?/p> <p>  (2) KlayGE</p> <p>  参考网站:<a >http://home.g365.net/enginedev/</a><br />  国内游戏开发高手自qC++开发的游戏引擎。KlayGE是一个开放源代码、跨q?br />台的游戏引擎Qƈ使用Python作脚本语a。KlayGE在LGPL协议下发行。感谢龚敏敏<br />先生Z国游戏开发事业所做出的A献?/p> <p>  (3) OGRE</p> <p>  参考网站:<a >http://www.ogre3d.org</a><br />  OGREQ面向对象的囑Ş渲染引擎Q是用C++开发的Q用灵zȝ面向对象3D引擎<br />。它的目的是让开发者能更方便和直接地开发基?Dg讑֤的应用程序或游戏?br />引擎中的cdҎ底层的系l库Q如QDirect3D和OpenGLQ的全部使用l节q行?br />抽象Qƈ提供了基于现实世界对象的接口和其它类?/p> <p>  5.8 U程</p> <p>  (1) C++ Threads</p> <p>  参考网站:<a >http://threads.sourceforge.net/</a><br />  q个库的目标是给E序员提供易于用的c,q些c被l承以提供在Linux环境<br />中很隄到的大量的线E方面的功能?/p> <p>  (2) ZThreads</p> <p>  参考网站:<a >http://zthread.sourceforge.net/</a><br />  一个先q的面向对象Q跨q_的C++U程和同步库?/p> <p>  5.9 序列?/p> <p>  (1) s11n</p> <p>  参考网站:<a >http://s11n.net/</a><br />  一个基于STL的C++库,用于序列化PODQSTL容器以及用户定义的类型?/p> <p>  (2) Simple XML Persistence Library</p> <p>  参考网站:<a >http://sxp.sourceforge.net/</a><br />  q是一个把对象序列化ؓXML的轻量的C++库?/p> <p>  5.10 字符?/p> <p>  (1) C++ Str Library</p> <p>  参考网站:<a >http://www.utilitycode.com/str/</a><br />  操作字符串和字符的库Q支持Windows和支持gcc的多U^台。提供高度优化的<br />代码Qƈ且支持多U程环境和UnicodeQ同时还有正则表辑ּ的支持?/p> <p>  (2) Common Text Transformation Library</p> <p>  参考网站:<a >http://cttl.sourceforge.net/</a><br />  q是一个解析和修改STL字符串的库。CTTL substringcd以用来比较,插入Q?br />替换以及用EBNF的语法进行解析?/p> <p>  (3) GRETA</p> <p>  参考网站:<a >http://research.microsoft.com/projects/greta/</a><br />  q是由微软研I的研Ih员开发的处理正则表达式的库。在型匚w的情?br />下有非常优秀的表现?/p> <p>  5.11 l合</p> <p>  (1) P::Classes</p> <p>  参考网站:<a >http://pclasses.com/</a><br />  一个高度可UL的C++应用E序框架。当前关注类型和U程安全的signal/slot<br />机制Qi/opȝ包括Z插g的网l协议透明的i/o架构Q基于插件的应用E序消息<br />日志框架Q访问sql数据库的cȝ{?/p> <p>  (2) ACDK - Artefaktur Component Development Kit</p> <p>  参考网站:<a >http://acdk.sourceforge.net/</a><br />  q是一个^台无关的C++lg框架Q类gJava或?NET中的框架Q反机Ӟ<br />U程QUnicodeQ废料收集,I/OQ网l,实用工具QXMLQ等{)Q以及对Java, P<br />erl, Python, TCL, Lisp, COM ?CORBA的集成?/p> <p>  (3) dlib C++ library</p> <p>  参考网站:<a >http://www.cis.ohio-state.edu/~kingd/dlib/</a><br />  各种各样的类的一个综合。大整数QSocketQ线E,GUIQ容器类,以及览?br />录的API{等?/p> <p>  (4) Chilkat C++ Libraries</p> <p>  参考网站:<a >http://www.chilkatsoft.com/cpp_libraries.asp</a><br />  q是提供zipQe-mailQ编码,S/MIMEQXML{方面的库?/p> <p>  (5) C++ Portable Types Library (PTypes)</p> <p>  参考网站:<a >http://www.melikyan.com/ptypes/</a><br />  q是STL的比较简单的替代品,以及可移植的多线E和|络库?/p> <p>  (6) LFC</p> <p>  参考网站:<a >http://lfc.sourceforge.net/</a><br />  哦,q又是一个尝试提供一切的C++?/p> <p>  5.12 其他?/p> <p>  (1) Loki</p> <p>  参考网站:<a >http://www.moderncppdesign.com/</a><br />  哦,你可能抱怨我早该和Boost一起介l它Q一个实验性质的库。作者在loki?br />把C++模板的功能发挥到了极致。ƈ且尝试把cM设计模式q样思想层面的东襉K过<br />库来提供。同时还提供了智能指针这h较实用的功能?/p> <p>  (2) ATL</p> <p>  ATL(Active Template Library)<br />  是一l小巧、高效、灵zȝc,q些cMؓ创徏可互操作的COMlg提供了基本的<br />设施?/p> <p>  (3) FC++: The Functional C++ Library<br />  q个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代?br />作。如果想要在OOP之外L另一分的乐趣Q可以去看看函数式程序设计的世界。大<br />师Peter Norvig?“Teach Yourself Programming in Ten Years”一文中将?br />数式语言列ؓ臛_应当学习?cȝE语a之一?/p> <p>  (4) FACT!</p> <p>  参考网站:<a >http://www.kfa-juelich.de/zam/FACT/start/index.html</a><br />  另外一个实现函数式语言Ҏ的?/p> <p>  (5) Crypto++<br />  提供处理密码Q消息验证,单向hashQ公匙加密系l等功能的免费库?/p> <p>  q有很多非常Ȁ动h心或者是极其实用的C++库,限于我们的水q以及文章的?br />q不能包括进来。在对于q些已经包含q来的库的介l中Q由于ƈ不是每一个我?br />都用过Q所以难免有偏颇之处Q请读者见谅?/p> <p>  6Q书c?/p> <p>  以前熊节先生曾撰文评论相对于JavaE序设计语言QC++的好书多如牛毛。荣耀<br />先生在《程序员》杂志上撰文《C++E序设计之四书五l》也本领域内几乎所有的<br />l典书籍作了全面的介l?M关于书的评论此时看来便是很多余的了。个人浅见,<br />除非你打以C++作ؓ唯一兴趣或者生存之本,一般读者确实没有够的旉和必?br />?0余本书籍全部阅读。更有参考h值的是荣耀先生的另一文章:《至应该阅<br />ȝ九本C++著作》,可以从下面的地址览到此文:</p> <p>  <a >http://www.royaloo.com/articles/articles_2003/9CppBooks.htm</a><br />  下面几本书对于走在C++初学之\上的读者是我们最愿意推荐l大家的Q?/p> <p>  (1) 《C++ Primer?/p> <p>  哦,也许你会抱怨我们ؓ什么不先介lTCPL,但对于走在学习之路上的入门者,<br />本书内容更ؓ全面Q更l易懂,我们U它为“C++的超U宝典”ƈ不过分。配?br />一本不错的习题解答《C++ Primer Answer Book》可以辅助你的学习之路?/p> <p>  (2) 《Essential C++?/p> <p>  如果说《C++ Primer》是C++领域的超U宝典,那么此书作ؓ掌握C++的大局?br />当之无愧。正如?NET大局观》一书能够让读者全?NETQ本书讲qCC++中最核心<br />的全部主题。书虽不厚,内容_Q不׃ؓ《C++ Primer》读者茶余饭后的主题?br />之作?/p> <p>  (3) 《The C++ Programming Language?/p> <p>  BjarneZ带来的C++教程Q真正能够告诉你怎么用才叫真正的C++的唯一一?br />书。虽然如同“某某程序设计语a”这L书籍会给大家一个内容全揽,入门到精<br />通的感觉Q但本书实不太适合初学者阅诅R如果你自认为是一名很有经验的C++E?br />序员Q那臛_也要反复咀嚼Bjarne先生所的若q内宏V?/p> <p>  (4) 《Effective C++》,《More Effective C++?/p> <p>  是的Q正如一些C++爱好者经总读过与没有读q上qC本作品来区分你是否是<br />C++高手。我们也极力推崇q两本著作。在各种介绍C++专家l验的书c里面,q两<br />本是最贴近语言本质Q看后最能够有脱胎换骨感觉的书,L书你需每日三省汝n<br />?/p> <p>  技术书c仁者见仁,q多的评论反无太多意义,p者喜好选择最适合自己?br />书方Z{?/p> <p> <br />  7Q资源网?/p> <p>  正如我们可以通过计算机历史上的重要h物了解计机史的发展QC++相关人物<br />的网站也可以使我们得到最有h值的参考与借鉴Q下面的人物我们认ؓ没有介绍?br />必要Q只因下面的人物在C++领域的地位众所周知Q我们只相关的资源q行|列?br />供读者学习,他们有的工作于贝实验室Q有的工作于知名~译器厂商,有的在不<br />断推q语a的标准化Q有的ؓ读者撰写了多部千古奇作…?br />  (1) Bjarne Stroustrup<br />  <a >http://www.research.att.com/~bs/</a></p> <p>  (2) Stanley B. Lippman<br />  <a >http://blogs.msdn.com/slippman/</a><br />  中文?<a >http://www.zengyihome.net/slippman/index.htm</a></p> <p>  (3) Scott Meyers<br />  <a >http://www.aristeia.com/</a></p> <p>  (4) David Musser<br />  <a >http://www.cs.rpi.edu/~musser/</a></p> <p>  (5) Bruce Eckel<br />  <a >http://www.bruceeckel.com</a></p> <p>  (6) Nicolai M. Josuttis<br />  <a >http://www.josuttis.com/</a></p> <p>  (7) Herb Sutter<br />  <a >http://www.gotw.ca/</a></p> <p>  (8) Andrei Alexandrescu<br />  <a >http://www.coderncppdesign.com/</a></p> <p>  (9) 侯捷先生<br />  <a >http://www.jjhou.com</a></p> <p>  (10) 孟岩先生<br />  先生J忙于工作,痴迷于技术,暂无个h主页Q关于先生的作品可以通过CSDN<br />的专栏和侯先生的主页讉K到?/p> <p>  (11) 荣耀先生<br />  <a >http://www.royaloo.com/</a></p> <p>  (12) 潘爱民先?br />  <a >http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm</a></p> <p>  除了上述大师的主外Q以下的l合cC++学习参考站Ҏ我们非常愿意向大?br />推荐的:</p> <p>  (1) CodeProject<br />  <a >http://www.codeproject.com</a></p> <p>  (2) CodeGuru<br />  <a >http://www.codeguru.com</a></p> <p>  (3) Dr. Dobb's Journal<br />  <a >http://www.ddj.com</a></p> <p>  (4) C/C++ Users Journal<br />  <a >http://www.cuj.com</a></p> <p>  (5) Cl视?br />  <a >http://www.c-view.org</a></p> <p>  (6) allaboutprogram<br />  <a >http://www.allaboutprogram.com</a><br />  其他资料</p> <p>  (1) ISO IEC JTC1/SC22/WG21 - C++Q标准C++的权威参?br />  <a >http://anubis.dkuug.dk/jtc1/sc22/wg21/</a></p> <p>  (2) C++ FAQ LITE ?Frequently Asked Questions: 最为全面的C++FAQ<br />  <a >http://www.sunistudio.com/cppfaq/index.html</a><br />  C/C++ 新闻l:<br />  你不妨尝试从q里提问和回{问题,很多不错的Q&A资源......</p> <p>  (1) .alt.comp.lang.learn.c-c++<br />  q个单些Q如果你和我一h个菜?/p> <p>  (2) .comp.lang.c++.moderated<br />嗯,q个昄水^高一?/p> <p>  (3) .comp.std.c++<br />  如果你需要讨论标准C++相关话题的话</p> <p>  8Q不得不写的l束?/p> <p>  l束的时候也是ȝ现状Q展望未来的时候。虽然C++从脱胎于C开始,一路艰<br />隑֝L走过来,但是无论如何C++已经取得了工业基的地位。文章列丄大量相关<br />资源是最好的证明Q而业界的大量用C++写成的品代码以及大量的C++职业工程<br />师则是最直接的证明。同Ӟ我们可以看到各个高校的计机专业都开设有C++q门<br />评Q网l上对于C++的学习讨Z从来都没有停q。但是,在Java?NET两大企业<br />开发^台的围攻下,lh的感觉是C++来“不行”了?/p> <p>  C++在面向企业的软g开发中Q在开发便h等斚w的确要比Java和C#差很多,<br />其中一个问题是C++语言本n比较复杂Q学习曲U比较陡峭,另外一个问题是C++?br />准化的时间太长,丧失了很多的壮大ZQ耗费了很多精力在厂商的之间的斗争?br />Q而C++的标准库M个完善的E序开发框架还~少太多太多的内容,各个W三方的<br />cd和框架又在一致性和完整性上没法和随q_提供的框架相提ƈ论。难道C++真的<br />要退出历史舞CQ?/p> <p>  从C++目前的活跃程度,以及应用现状来说是完全能够肯定C++仍然是Y件工?br />的基Q也不会退出历史舞台的。另外从BoostQLokiq些库中我们也能够看到C++<br />的发展非常活跃,对于新技术新思维非常Ȁq,C++仍然q泛受到x。从ACE在高<br />性能通信领域的应用,以及MTLq样的库在数D领域的表现Q我们可以看?br />C++在高性能应用场合下的不可替代的作用,而嵌入式pȝq样的内存受限开发^?br />Q比如Symbian OS上,C++已经发挥着q且发挥更大的作用。可以预见的是以后的<br />软g无论上层的应用怎么变,它的底层核心都会是由C/C++q样的系l软g~写?br />Q比如Java虚拟机,.NET Framwork。因为只有这LpȝUY件才能完全彻底的?br />挥机器的功能?/p> <p>  需要看到的是两个趋势,一个趋势是C++变得更加复杂Q更加学院派Q通过模板<br />{有潜力的语法因素构造越来越_y的库成ؓ了现代C++的热点,虽然在利用库实现<br />新的~程范式Q乃臌计模式等斚w很有开创意义,也确实生了一些能够便捷开<br />发的工具Q但是更多的是把C++变得更加强大Q更加复杂,也更加难懂,g也更?br />学院z,不得不说它正在向边缘化道路发展。另一个趋势是C++在主的企业应用开<br />发中已经逐渐退ZQERPq样的企业Y件开发中基本上不会考虑C++Q除非需要?br />虑性能或者和遗留代码的集成这些因素。C++退守到pȝU别语言Q成Y件工业的<br />基础是大势所。然而反思一下,真的是退守么Q自从STL出现Q无数的人风起云?br />的开始支持C++,他们狂呼“我看到深夜消失了,目标软g工程的出现。我看到了可<br />l护的代码。”是的,STL在可l护性下做得如此。但是又怎样呢?STL为C++?br />q了C软g工程的道路,而在上层应用E序软g开发领域这块场地早不单独属?br />C++,很多E序设计语言都做得很Q疯狂的支持者会毫不犹U地说我们应当支持<br />C++,因ؓ它是世界上最的语言。而坦率地_你的腰杆真的那么么Q也许只?br />在逃避一些事实。C++是优U的,q不可否认,STL的出现让C++一度走上了最辉煌?br />时刻Q然而现在看来……我的一位恩师曾aQ真正能够将STL应用得淋漓尽致的人很<br />保守地说国内也不过200人,或许不加入STL能够使C++向着它应当发展的方向发展<br />的更好,而现在看来,C++也应当回首到真正属于他的那一片圣C…?/p> <p>参考资?/p> <p>本文成文时参考了以下资源Q?/p> <p>1、《程序员?004q?月,3月,“C++ E序设计之四书五l?荣耀<br />2、水'木清华BBS C++版精华区<br />3?a >http://jjhou.csdn.net</a><br />4?a >http://www.royaloo.com</a><br />5?a >http://www.zengyihome.net</a><br />6、C/C++ 开发h员:充实您的 XML 工具?</p> <img src ="http://www.shnenglu.com/Lee/aggbug/74811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2009-02-25 00:26 <a href="http://www.shnenglu.com/Lee/archive/2009/02/25/74811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>二进制、八q制、十q制、十六进制之间{换(转)http://www.shnenglu.com/Lee/archive/2009/02/13/73736.htmlDavid LeeDavid LeeFri, 13 Feb 2009 10:15:00 GMThttp://www.shnenglu.com/Lee/archive/2009/02/13/73736.htmlhttp://www.shnenglu.com/Lee/comments/73736.htmlhttp://www.shnenglu.com/Lee/archive/2009/02/13/73736.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/73736.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/73736.html 一?十进制与二进制之间的转换
Q?Q?十进制{换ؓ二进Ӟ分ؓ整数部分和小数部?
?整数部分
ҎQ除2取余法,xơ将整数部分除以2Q余Cؓ该位权上的数Q而商l箋除以2Q余数又Z一个位权上的数Q这个步骤一直持l下去,直到商ؓ0为止Q最后读数时候,从最后一个余数读P一直到最前面的一个余数。下面D例:
例:十q制?68转换Zq制

得出l果 十q制?68转换Zq制Q(10101000Q?
分析:W一步,?68除以2,?4,余数??
W二步,商84除以2Q商42余数??
W三步,商42除以2Q商21余数??
W四步,商21除以2Q商10余数??
W五步,商10除以2Q商5余数??
W六步,商5除以2Q商2余数??
W七步,商2除以2Q商1余数??
W八步,商1除以2Q商0余数??
W九步,LQ因为最后一位是l过多次除以2才得到的Q因此它是最高位Q读数字从最后的余数向前读,?0101000

Q?Q?数部分
ҎQ乘2取整法,卛_数部分乘以2Q然后取整数部分Q剩下的数部分l箋乘以2Q然后取整数部分Q剩下的数部分又乘?Q一直取到小数部?
为零为止。如果永q不能ؓӞ同十进制数的四舍五入一P按照要求保留多少位小数时Q就Ҏ后面一位是0q是1Q取舍,如果是零Q舍掉,如果?Q向入一位。换句话说就??入。读数要从前面的整数d后面的整敎ͼ下面举例Q?
?Q将0.125换算Zq制

得出l果Q将0.125换算Zq制Q?.001Q?
分析Q第一步,?.125乘以2Q得0.25,则整数部分ؓ0,数部分?.25;
W二? 小数部?.25乘以2,?.5,则整数部分ؓ0,数部分?.5;
W三? 小数部?.5乘以2,?.0,则整数部分ؓ1,数部分?.0;
W四?L,从第一位读?d最后一?即ؓ0.001?


?,?.45转换Zq制Q保留到数点第四位Q?


大家从上面步骤可以看出,当第五次做乘法时候,得到的结果是0.4Q那么小数部分l乘?Q得0.8Q?.8又乘?的,?.6q样一直乘下去Q最后不可能得到数部分为零Q因此,q个时候只好学习十q制的方法进行四舍五入了Q但是二q制只有0?两个Q于是就出现0?入。这个也是计机在{换中会生误差,但是׃保留位数很多Q精度很高,所以可以忽略不计?
那么Q我们可以得出结果将0.45转换Zq制U等?.0111
上面介绍的方法是十进制{换ؓZq制的方法,需要大家注意的是:
1Q?十进制{换ؓ二进Ӟ需要分成整数和数两个部分分别转换
2Q?当{换整数时Q用的除2取余法,而{换小数时候,用的是乘2取整?
3Q?注意他们的读数方?
因此Q我们从上面的方法,我们可以得出十进制数168.125转换Zq制?0101000.001,或者十q制数{换ؓ二进制数U等?0101000.0111?

Q?Q?二进制{换ؓ十进?不分整数和小数部?
ҎQ按权相加法Q即二q制每位上的C以权Q然后相加之和即是十q制数。例
二q制?01.101转换为十q制数?

得出l果Q(101.101Q?=(5.625)10
大家在做二进制{换成十进刉要注意的?
1Q?要知道二q制每位的权?
2Q?要能求出每位的?


二?二进制与八进制之间的转换
首先Q我们需要了解一个数学关p,?3=8Q?4=16Q而八q制和十六进制是用这
关系衍生而来的,即用三位二进制表CZ位八q制Q用四位二进制表CZ位十六进制数?
接着Q记?个数????Q?3=8?2=4?1=2?0=1Q。现在我们来l习二进制与八进制之间的转换?
Q?Q?二进制{换ؓ八进?
ҎQ取三合一法,即从二进制的数点ؓ分界点,向左Q向叻I每三位取成一位,接着这三位二进制按权相加,得到的数是一位八位二q制敎ͼ然后Q按序q行排列Q小数点的位|不变,得到的数字就是我们所求的八进制数。如果向左(向右Q取三位后,取到最高(最低)位时候,如果无法凑三位Q可以在数Ҏ左边Q最双Q,x数的最高位Q最低位Q添0Q凑三位。例
①将二进制数101110.101转换为八q制

得到l果Q将101110.101转换为八q制?6.5

?二q制?101.1转换为八q制

得到l果Q将1101.1转换为八q制?5.4

Q?Q?八q制转换Zq制
ҎQ取一分三法,卛_一位八q制数分解成三位二进制数Q用三位二进制按权相加去凑这位八q制敎ͼ数点位|照旧。例Q?
?八q制?7.54转换Zq制

因此Q将八进制数67.54转换Zq制Cؓ110111.101100Q即110111.1011
大家从上面这道题可以看出Q计八q制转换Zq制
首先Q将八进制按照从左到叻I每位展开Z位,数点位|不?
然后Q按每位展开?2Q?1Q?0Q即4??Q三位去做凑敎ͼ即a×22+ b×21 +c×20=该位上的敎ͼa=1或者a=0Qb=1或者b=0Qc=1或者c=0Q?abc排列是该位的二q制?
接着Q将每位上{换成二进制数按顺序排?
最后,得C八进制{换成二进制的数字?
以上的方法就是二q制与八q制的互换,大家在做题的时候需要注意的?
1Q?他们之间的互换是以一位与三位转换Q这个有别于二进制与十进制{?
2Q?大家在做?和去0的时候要注意Q是在小数点最左边或者小数点的最双Q即整数的最高位和小数的最低位Q才能添0或者去0Q否则将产生错误

三?二进制与十六q制的{?
ҎQ与二进制与八进制{换相|只不q是一位(十六Q与四位Q二q制Q的转换Q下面具体讲?
Q?Q?二进制{换ؓ十六q制
ҎQ取四合一法,即从二进制的数点ؓ分界点,向左Q向叻I每四位取成一位,接着这四位二进制按权相加,得到的数是一位十六位二进制数Q然后,按顺序进行排列,数点的位置不变Q得到的数字是我们所求的十六q制数。如果向左(向右Q取四位后,取到最高(最低)位时候,如果无法凑四位Q可以在数Ҏ左边Q最双Q,x数的最高位Q最低位Q添0Q凑_位?
①例Q将二进?1101001.1011转换为十六进?

得到l果Q将二进?1101001.1011转换为十六进制ؓE9.B


?例:?01011.101转换为十六进?

因此得到l果Q将二进?01011.101转换为十六进制ؓ2B.A



(2)十六进制{换ؓ二进?
ҎQ取一分四法,卛_一位十六进制数分解成四位二q制敎ͼ用四位二q制按权相加dq位十六q制敎ͼ数点位|照旧?
①将十六q制6E.2转换Zq制?

因此得到l果Q将十六q制6E.2转换Zq制?1101110.0010?10110.001

四、八q制与十六进制的转换
ҎQ一般不能互相直接{换,一般是八q制Q或十六q制Q{换ؓ二进Ӟ然后再将二进制{换ؓ十六q制Q或八进ӞQ小数点位置不变。那么相应的转换请参照上面二q制与八q制的{换和二进制与十六q制的{


五、八q制与十q制的{?
Q?Q八q制转换为十q制
ҎQ按权相加法Q即八q制每位上的C以位权,然后相加之和x十进制数?
例:①将八进制数67.35转换为十q制

Q?Q十q制转换为八q制
十进制{换成八进制有两种ҎQ?
1Q间接法Q先十q制转换成二q制Q然后将二进制又转换成八q制
2Q直接法Q前面我们讲q,八进制是׃q制衍生而来的,因此我们可以采用与十q制转换Zq制相类似的ҎQ还是整数部分的转换和小数部分的转换Q下面来具体讲解一下:
①整数部?
ҎQ除8取余法,xơ将整数部分除以8Q余Cؓ该位权上的数Q而商l箋除以8Q余数又Z一个位权上的数Q这个步骤一直持l下去,直到商ؓ0为止Q最后读数时候,从最后一个余数vQ一直到最前面的一个余数?
②小数部?
ҎQ乘8取整法,卛_数部分乘以8Q然后取整数部分Q剩下的数部分l箋乘以8Q然后取整数部分Q剩下的数部分又乘?Q一直取到小数部分ؓ零ؓ止。如果永q不能ؓӞ同十进制数的四舍五入一P暂取个名字叫3?入?
例:十q制?96.703125转换为八q制?
解:先将q个数字分ؓ整数部分796和小数部?.703125
整数部分

数部分

因此Q得到结果十q制796.703125转换八进制ؓ1434.55
上面的方法大家可以验证一下,你可以先十q制转换Q然后在转换为八q制Q这L得到的结果是否一?

六、十六进制与十进制的转换
十六q制与八q制有很多相g处,大家可以参照上面八进制与十进制的转换自己试试q两个进制之间的转换?
通过上面对各U进制之间的转换Q我们可以将前面的{换图重新完善一下:


本文介绍了二q制、十q制、八q制、十六进制四U进制之间相互的转换Q大家在转换的时候要注意转换的方法,以及步骤Q特别是十进制{换ؓ期于三种q制之间Q要分ؓ整数部分和小数部分,最后就是小数点的位|。但是要保证考试中不出现错误q是需要大家经常练习,q样才能熟能生y?


David Lee 2009-02-13 18:15 发表评论
]]>
GDI & GDI+ http://www.shnenglu.com/Lee/archive/2009/02/07/73170.htmlDavid LeeDavid LeeSat, 07 Feb 2009 11:37:00 GMThttp://www.shnenglu.com/Lee/archive/2009/02/07/73170.htmlhttp://www.shnenglu.com/Lee/comments/73170.htmlhttp://www.shnenglu.com/Lee/archive/2009/02/07/73170.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/73170.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/73170.html1.基本概念

  GDI在Windows中定义ؓGraphics Device InterfaceQ即囑Ş讑֤接口Q是Windows API(Application Programming Interface)的一个重要组成部分。它是Windows囑Ş昄E序与实际物理设备之间的桥梁QGDI使得用户无需兛_具体讑֤的细节,而只需在一个虚拟的环境(即逻辑讑֤)中进行操作。它的桥梁作用体现在Q?br />
  (1)用户通过调用GDI函数逻辑I间的操作{化ؓ具体针对讑֤驱动E序的调用?br />
  为实现图形设备无x,Windows 的绘图操作在一个设备描q表上进行。用h有自q"逻辑坐标"pȝQ它独立于实际的物理讑֤Q与"讑֤坐标"相对应。开发Windows应用E序ӞE序员关心的是逻辑坐标Q我们在逻辑坐标pMl图Q利用GDI逻辑H口映射到物理设备上?br />
  (2)GDI能检具体设备的能力Qƈ依据具体的设备以最优方式驱动这些设备,完成真实的显C?br />
  GDI函数大致可分cMؓQ设备上下文函数(如GetDC、CreateDC、DeleteDC)?ȝ函数(如LineTo、Polyline、Arc)、填充画囑և?如Ellipse、FillRect、Pie)、画囑ֱ性函?如SetBkColor、SetBkMode、SetTextColor)、文本、字体函?如TextOut、GetFontData)、位囑և?如SetPixel、BitBlt、StretchBlt)、坐标函?如DPtoLP、LPtoDP、ScreenToClient、ClientToScreen)、映函?如SetMapMode、SetWindowExtEx、SetViewportExtEx)、元文g函数(如PlayMetaFile、SetWinMetaFileBits)、区域函?如FillRgn、FrameRgn、InvertRgn)、\径函?如BeginPath、EndPath、StrokeAndFillPath)、裁剪函?如SelectClipRgn、SelectClipPath){?br />
  GDI虽然使程序员得到了一定程度的解脱Q但是其~程方式仍很ȝ。譬如,昄一张位图,E序员需要进?装入位图―读取位图文件头信息―启用设备场景―调色板变换"{一q串操作。而有了GDI+Q这些问题便q刃而解了?br />
  ֐思义QGDI+是GDI的增强版。它是微软在Windows 2000以后操作pȝ中提供的新接口,光过一套部|ؓ托管代码的类来展玎ͼq套c被UCؓGDI+?托管cL?。GDI+主要提供了以下三cL?

  (1) 二维矢量囑ŞQGDI+提供了存储图形基元自w信息的c?或结构体)、存储图形基元绘制方式信息的cM及实际进行绘制的c;

  (2) 囑փ处理Q大多数囄都难以划定ؓ直线和曲U的集合Q无法用二l矢量图形方式进行处理。因此,GDI+为我们提供了Bitmap、Image{类,它们可用于显C、操作和保存BMP、JPG、GIF{图像格式?br />
  (3) 文字昄QGDI+支持使用各种字体、字号和样式来显C文本?br />
  GDI接口是基于函数的Q而GDI+是基于C++cȝ对象化的应用E序~程接口Q因此用v来比GDI要方ѝ?br />
  2.例程q?/strong>

  单击此处下蝲本文例程源代码?br />
  本文后箋的讲解都Zq样的一个例子工E?例程的开发环境ؓVisual C++6.0Q操作系lؓWindows XP)Q它是一个基于对话框的MFC应用E序Q包?个父菜单Q?br />
  (1) GDI

  GDI父菜单下包括一个子菜单Q?br />
IDQIDM_GDI_DRAW_LINE captionQ画U?br />
  单击事gQ在H口l制正旋曲线

  (2) GDI+

  DIB位图父菜单下包括两个子菜单:

a. IDQIDM_GDIP_DRAW_LINE captionQ画U?br />
  单击事gQ在H口l制正旋曲线

b. captionQ新增功能,其下又包括下列子菜单Q?br />
  (?IDQIDM_Gradient_Brush captionQ渐变画?br />
  单击事gQ在H口演示GDI+的渐变画刷功?br />
  (?IDQIDM_Cardinal_Spline captionQ基数样?br />
  单击事gQ在H口演示GDI+的基数样条函数功?br />
  (?IDQIDM_Transformation_Matrix captionQ变形和矩阵对象

  单击事gQ在H口演示GDI+的变形和矩阵对象功能

  (?IDQIDM_Scalable_Region captionQ可伸羃区域

  单击事gQ在H口演示GDI+的可伸羃区域功能

  (?IDQIDM_IMAGE captionQ图?br />
  单击事gQ在H口演示GDI+的多U图像格式支持功?br />
  (?IDQIDM_Alpha_Blend captionQAlpha混合

  单击事gQ在H口演示GDI+的Alpha混合功能

  (?IDQIDM_TEXT captionQ文?br />
  单击事gQ在H口演示GDI+的强大文本输?br />
  后箋章集中在对上q菜单单M件消息处理函数的讲解Q下面的代码是整个对话框cCGdiexampleDlg的消息映:

BEGIN_MESSAGE_MAP(CGdiexampleDlg, CDialog)
//{{AFX_MSG_MAP(CGdiexampleDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_COMMAND(IDM_GDI_DRAW_LINE, OnGdiDrawLine)
ON_COMMAND(IDM_GDIP_DRAW_LINE, OnGdipDrawLine)
ON_COMMAND(IDM_Gradient_Brush, OnGradientBrush)
ON_COMMAND(IDM_Cardinal_Spline, OnCardinalSpline)
ON_COMMAND(IDM_Transformation_Matrix, OnTransformationMatrix)
ON_COMMAND(IDM_Scalable_Region, OnScalableRegion)
ON_COMMAND(IDM_IMAGE, OnImage)
ON_COMMAND(IDM_Alpha_Blend, OnAlphaBlend)
ON_COMMAND(IDM_TEXT, OnText)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

3.GDI~程

  "GDI"菜单下的"ȝ"子菜单单M件消息处理函数的代码如下Q?br />

void CGdiexampleDlg::OnGdiDrawLine()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 //逻辑坐标与设备坐标变?br /> CRect rect;
 GetClientRect(&rect);
 dc.SetMapMode(MM_ANISOTROPIC);
 dc.SetWindowOrg(0, 0);
 dc.SetWindowExt(rect.right, rect.bottom);
 dc.SetViewportOrg(0, rect.bottom / 2);
 dc.SetViewportExt(rect.right, - rect.bottom);
 //创徏l制正旋曲线的penq将光入讑֤上下?br /> CPen pen(PS_SOLID, 1, RGB(255, 0, 0));
 HGDIOBJ oldObject = dc.SelectObject(pen.GetSafeHandle());
 //l制正旋曲线
 dc.MoveTo(0, 0);
 for (int i = 0; i < rect.right; i++)
 {
  dc.LineTo(i, 100 *sin(2 *(i / (rect.right / 5.0)) *PI));
 }
 //创徏l制x轴的penq将光入讑֤上下?br /> CPen penx(PS_SOLID, 1, RGB(0, 0, 255));
 dc.SelectObject(penx.GetSafeHandle());
 //l制X?br /> dc.MoveTo(0, 0);
 dc.LineTo(rect.right, 0);
 //恢复原先的pen
 dc.SelectObject(oldObject);
}

  单击q个按钮Q会出现如图1所C的效果Q我们来Ҏq行解读?br />
WindowsGDI和GDI+~程实例全剖?2)
? l制正旋曲线

  前文提到QGDI~程需q行讑֤坐标和逻辑坐标的{化。而屏q上的设备坐标通常会按客户坐标l出Q客户坐标依赖于H口的客户区域,其v始位|位于客户区域的左上角。ؓC区别,?l出了设备坐标和用户逻辑坐标的示例?br />
WindowsGDI和GDI+~程实例全剖?2)
? 讑֤坐标与逻辑坐标

  讑֤坐标与逻辑坐标的{换关pd下:

WindowsGDI和GDI+~程实例全剖?2)
WindowsGDI和GDI+~程实例全剖?2)

  公式中的<Xvorg, Yvorg>是设备空间中视口的原点,?lt; Xworg, Yworg >是逻辑I间中窗口的原点?Xwext/Xvext和Ywext/Yvext分别是窗口与视口水^和垂直范围的比例?br />
  因此Q经q程序中的dc.SetWindowOrg (0Q?) 和dc.SetViewportOrg (0Qrect.bottom/2)语句我们讄了视口和H口的原点;而经q程序中的dc.SetWindowExt (rect.rightQrect.bottom) 和dc.SetViewportExt (rect.rightQ?rect.bottom) 语句我们讄了视口和H口的范围。由于视口和H口的纵坐标方向相反Q设|视口的垂直范围倹{这h们得C一个逻辑坐标原点为客户区水^方向最左边和垂直方向居中的坐标p,我们在这个坐标系上直接绘制正旋曲U,不需要再理睬Windows对话框客户区坐标了?br />
  void CGdiexampleDlg::OnGdiDrawLine()函数中未指定逻辑讑֤和物理设备的映射模式Q则为缺省的MM_TEXT。在q种模式下,一个逻辑单位对应于一个像素点。映模式是GDI中的一个重要概念,其它的映模式还有MM_LOENGLlSH、MM_HIENGLISH、MM_LOMETRIC和MM_HIMETRIC{。我们可以通过如下语句指定映射模式为MM_TEXTQ?br />

dc.SetMapMode(MM_TEXT);

  值得一提的是,从上qC码可以看出:在GDI~程中,几乎所有的操作都围l设备上下文dc展开。的,q正是GDI~程的特点!讑֤上下文是Windows 使用的一U结构,所有GDI操作前都需取得特定讑֤的上下文Q函C的CClientDC dc (this) 语句完成q一功能?br />
  归纳可得Q利用GDIq行囑Ş、图像处理的一般操作步骤ؓQ?br />
  1. 取得指定H口的DCQ?br />
  2. 定使用的坐标系及映方式;

  3. q行囑Ş、图像或文字处理Q?br />
  4. 释放所使用的DC?br />
  4.GDI+~程

  "GDI+"菜单下的"ȝ"子菜单单M件消息处理函数的代码如下Q?

void CGdiexampleDlg::OnGdipDrawLine()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 //逻辑坐标与设备坐标变?br /> CRect rect;
 GetClientRect(&rect);
 dc.SetMapMode(MM_ANISOTROPIC);
 dc.SetWindowOrg(0, 0);
 dc.SetWindowExt(rect.right, rect.bottom);
 dc.SetViewportOrg(0, rect.bottom / 2);
 dc.SetViewportExt(rect.right, - rect.bottom);

 //创徏Graphics对象
 Graphics graphics(dc);
 //创徏pen
 Pen myPen(Color::Red);
 myPen.SetWidth(1);
 //L旋曲U?br /> for (int i = 0; i < rect.right; i++)
 {
  graphics.DrawLine(&myPen, i, 100 *sin(2 *(i / (rect.right / 5.0)) *PI), i +
1, 100 *sin(2 *((i + 1) / (rect.right / 5.0)) *PI));
 }
 //画X?br /> myPen.SetColor(Color::Blue);
 graphics.DrawLine(&myPen, 0, 0, rect.right, 0);
}

  ׃我们使用的是Visual C++6.0而非VS.NetQ我们需要下载微软的GDIPLUS支持包。在微Y官方|站下蝲旉认证Windows为正版,我们可从q个地址下蝲Qhttp://www.codeguru.com/code/legacy/gdi/GDIPlus.zip。一个完整的GDI+支持包至包括如下文Ӟ

  (1)头文Ӟgdiplus.h

  (2)动态链接库?lib文gQgdiplus.lib

  (3)动态链接库?dll文gQgdiplus.dll

  了(1)?2)E序不能~译Q少?3)E序能以׃nDLL的方式编译但是不能运行,q行时找不到.dll文g?br />
  Z得Visual C++6.0支持GDI+Q我们需要在使用GDI+对象的文件的开头添加如下代码:

#define UNICODE
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
#include "c:\gdiplus\includes\gdiplus.h"
using namespace Gdiplus;
#pragma comment(lib, "c:\gdiplus\lib\gdiplus.lib")

  在Visual C++中用GDI+必须先进行GDI+的初始化Q我们在CWinAppzcȝInitInstance函数中进行此工作是最好的Q?br />

///////////////////////////////////////
CGdiexampleApp initialization

BOOL CGdiexampleApp::InitInstance()
{
 AfxEnableControlContainer();

 // Standard initialization

 #ifdef _AFXDLL
  Enable3dControls(); // Call this when using MFC in a shared DLL
 #else
  Enable3dControlsStatic(); //

Call this when linking to MFC statically
 #endif

 //初始化gdiplus的环?br /> GdiplusStartupInput gdiplusStartupInput;
 ULONG_PTR gdiplusToken;
 // 初始化GDI+.
 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

 CGdiexampleDlg dlg;
 m_pMainWnd = &dlg;
 int nResponse = dlg.DoModal();
 if (nResponse == IDOK){}
 else if (nResponse == IDCANCEL){}

 //关闭gdiplus的环?br /> GdiplusShutdown(gdiplusToken);

 return FALSE;
}


  单击"GDI+"菜单下的"ȝ"子菜单,也会出现如图1所C的效果。观察void CGdiexampleDlg::OnGdipDrawLine() 函数Q我们发现用GDI+q行囑Ş、图像操作的步骤为:

  (1)创徏 Graphics 对象QGraphics 对象表示GDI+l图表面Q是用于创徏囑Ş囑փ的对象;

  (2)使用 Graphics 对象l制U条和Ş状、呈现文本或昄与操作图像?br />
  Graphics 对象是GDI+的核心,GDI中设备上下文dc和Graphics 对象的作用相|但在GDI中用的是基于句柄的~程模式Q而GDI+中用的则是Z对象的编E模式。Graphics装了GDI+ l图面,而且此类无法被承,它的所有成员函数都不是虚函数?br />
  下面Q我们来逐个用实际代码实现GDI+的新增功能,q些新增功能包括Q渐变的d(Gradient Brushes)、基数样条函?Cardinal Splines)、持久的路径对象(Persistent Path Objects)、变形和矩阵对象(Transformations &Matrix Object)、可伸羃区域(Scalable Regions)、Alpha混合(Alpha Blending)和丰富的囑փ格式支持{?p>渐变的画?br />
  GDI+提供了用于填充图形、\径和区域的线性渐变画刷和路径渐变d?br />
  U性渐变画刷用渐变颜色来填充囑Ş?br />
  当用路径渐变d填充囑ŞӞ可指定从囑Ş的一部分U至另一部分时画刷颜色的变化方式。例如,我们可以只指定图形的中心颜色和边~颜Ԍ当画刷从囑Ş中间向外边缘UdӞd会逐渐从中心颜色变化到边缘颜色?

void CGdiexampleDlg::OnGradientBrush()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 CRect rect;
 GetClientRect(&rect);
 //创徏Graphics对象
 Graphics graphics(dc);
 //创徏渐变d
 LinearGradientBrush lgb(Point(0, 0), Point(rect.right, rect.bottom), Color::Blue, Color::Green);
 //填充
 graphics.FillRectangle(&lgb, 0, 0, rect.right, rect.bottom);
}

  本程序用线性渐变画P当画刷从客户区左上角Ud客户区右下角的过E中Q颜色逐渐p色{变ؓl色?br />
WindowsGDI和GDI+~程实例全剖?3)
? GDI+渐变d

  基数h函数

  GDI+支持基数hQ基数样条指的是一q串单独的曲U,q些曲线q接h形成一条较大的曲线。样条由?Pointl构?的数l指定,q过该数l中的每一个点。基数样条^滑地I过数组中的每一个点(不出现尖?Q因此比用直U连接创建的路径_?br />
void CGdiexampleDlg::OnCardinalSpline()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 //创徏Graphics对象
 Graphics graphics(dc);
 Point points[] =
 {
  Point(0, 0), Point(100, 200), Point(200, 0), Point(300, 200), Point(400, 00)
 };
 //直接ȝ
 for (int i = 0; i < 4; i++)
 {
  graphics.DrawLine(&Pen(Color::Blue, 3), points[i], points[i + 1]);
 }
 //利用基数hȝ
 graphics.DrawCurve(&Pen(Color::Red, 3), points, 5);
}

  ?演示了直接连U和l过基数hqx拟合后的U条的对比,后者的曲线(Curve)没有角。这个工作我们在中学的数学课上把L的点q接成曲U时做过?br />
WindowsGDI和GDI+~程实例全剖?3)
? GDI+基数h

 

持久的\径对?br />
  在GDI中,路径隶属于一个设备上下文Q一旦设备环境指针超q它的生存期Q\径也会被删除。利用GDI+Q可以创建ƈl护与Graphics对象分开的GraphicsPath 对象Q它不依赖于Graphics对象的生存期?br />
  变Ş和矩阵对?br />
  GDI+提供了Matrix对象Q它是一U可以变Ş(旋{、^UR羃攄) 易灵zȝ强大工具QMatrix对象需与要被变形的对象联合使用。对于GraphicsPathc,我们可以使用其成员函数Transform接收Matrix参数用于变Ş?br />

void CGdiexampleDlg::OnTransformationMatrix()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 //创徏Graphics对象
 Graphics graphics(dc);
 GraphicsPath path;
 path.AddRectangle(Rect(250, 20, 70, 70));
 graphics.DrawPath(&Pen(Color::Black, 1), &path); // 在应用变形矩阵之前绘制矩?br /> // 路径变Ş
 Matrix matrix1, matrix2;

 matrix1.Rotate(45.0f); //旋{时?5?br /> path.Transform(&matrix1); //应用变Ş
 graphics.DrawPath(&Pen(Color::Red, 3), &path);

 matrix2.Scale(1.0f, 0.5f); //转化成ؓq四边形法?br /> path.Transform(&matrix2); //应用变Ş
 graphics.DrawPath(&Pen(Color::Blue, 3), &path);
}

  ?演示了正方Şl过旋{和拉怹后的效果Q黑色的为原始图形,U色的ؓ旋{45度之后的囑ŞQ蓝色的为经q拉ؓq四边形后的图形?

WindowsGDI和GDI+~程实例全剖?4)
? GDI+变Ş和矩阵对?/div>

  可׾~区?br />
  GDI+通过对区?Region)的支持极大地扩展了GDI。在GDI 中,区域存储在设备坐标中Q可应用于区域的唯一变Ş是^UR但是在GDI +中,区域存储在全局坐标(世界坐标)中,可对区域利用变Ş矩阵q行变Ş(旋{、^UR羃攄)?br />
void CGdiexampleDlg::OnScalableRegion()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 //创徏Graphics对象
 Graphics graphics(dc);
 //创徏GraphicsPath
 GraphicsPath path;
 path.AddLine(100, 100, 150, 150);
 path.AddLine(50, 150, 150, 150);
 path.AddLine(50, 150, 100, 100);
 //创徏Region
 Region region(&path);
 //填充区域
 graphics.FillRegion(&SolidBrush(Color::Blue), &region);
 //区域变Ş
 Matrix matrix;
 matrix.Rotate(10.0f); //旋{时?0?br /> matrix.Scale(1.0f, 0.3f); //拉
 region.Transform(&matrix); //应用变Ş
 //填充变Ş后的区域
 graphics.FillRegion(&SolidBrush(Color::Green), &region);
}

  上述E序中以蓝色填充一个三角Ş区域Q接着此区域旋{和拉伸,再次昄Q其效果如图6?br />
WindowsGDI和GDI+~程实例全剖?4)
? GDI+区域变Ş

丰富的图像格式支?br />
  GDI +提供了Image、Bitmap 和Metafile c,方便用户q行囑փ格式的加载、操作和保存。GDI+支持的图像格式有BMP、GIF、JPEG、EXIF、PNG、TIFF、ICON、WMF、EMF{,几乎늛了所有的常用囑փ格式?br />

void CGdiexampleDlg::OnImage()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 //创徏Graphics对象
 Graphics graphics(dc);
 Image image(L "d:\1.jpg");
 //在矩形区域内昄jpg囑փ
 Point destPoints1[3] =
 {
  Point(10, 10), Point(220, 10), Point(10, 290)
 };
 graphics.DrawImage(&image, destPoints1, 3);
 //在^行四边Ş区域内显Cjpg囑փ
 Point destPoints2[3] =
 {
  Point(230, 10), Point(440, 10), Point(270, 290)
 };
 graphics.DrawImage(&image, destPoints2, 3);
}

  上述E序D盘根目录下文件名?1.jpg"的jpg囑փ以矩阵和q四边形两U方式显C,效果如图7?br />
WindowsGDI和GDI+~程实例全剖?5)
? GDI+多种囑փ格式支持

  由此我们可以看出QGDI+在图像显C和操作斚w的确比GDI单许多。回忆我们在《Visual C++中DDB与DIB位图~程全攻略》一文中所介绍的用GDI昄位图的方式,其与GDI+囑փ处理的难易程度真是有天壤之别?p>Alpha混合

  Alpha允许两个物体؜合v来显C,?D气氛和场景渲染等斚w有广泛应用。它?雑֌"囑փQ得一个图像着色在另一个半透明的图像上Q呈CU朦胧美。我们知道,一个像素可用RQGQB三个l度来表C,我们可以再加上第4个即QAlphal度(channel)Q表征透明E度?br />

void CGdiexampleDlg::OnAlphaBlend()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 //创徏Graphics对象
 Graphics graphics(dc);
 //创徏ColorMatrix
 ColorMatrix ClrMatrix =
 {
  1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
  0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
  0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
  0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
  0.0f, 0.0f, 0.0f, 0.0f, 1.0f
 };
 //ColorMatrix赋给ImageAttributes
 ImageAttributes ImgAttr;
 ImgAttr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
 //在矩形区域内昄jpg囑փ
 Image img1(L "d:\1.jpg");
 Point destPoints1[3] =
 {
  Point(10, 10), Point(220, 10), Point(10, 290)
 };
 graphics.DrawImage(&img1, destPoints1, 3);
 //Alpha混合
 Image img2(L "d:\2.jpg");
 int width, height;
 width = img2.GetWidth();
 height = img2.GetHeight();
 graphics.DrawImage(&img2, RectF(10, 10, 210, 280), 0, 0, width, height,UnitPixel, &ImgAttr);
 //在^行四边Ş区域内显Cjpg囑փ
 Point destPoints2[3] =
 {
  Point(230, 10), Point(440, 10), Point(270, 290)
 };
 graphics.DrawImage(&img1, destPoints2, 3);
 //Alpha混合
 graphics.DrawImage(&img2, destPoints2, 3, 0, 0, width, height, UnitPixel,&ImgAttr);
}

  上述E序中将D盘根目录下文件名?1.jpg"的图像以矩阵和^行四边Ş两种方式昄Q然后将文g名ؓ?2.jpg"的图像与之进行؜合,其效果如??br />
WindowsGDI和GDI+~程实例全剖?6)
? GDI+ Alpha混合

  Z能进行Alpha混合Q我们需要用ImageAttributescdColorMatrix矩阵QImageAttributes可以q行颜色、灰度等调整从而达到控制图像着色方式的目的。ColorMatrix是ImageAttributescd多数函数的参敎ͼ它包含了Alpha、Red、Green、Bluel度的|以及另一lwQ顺序ؓRGBaw?br />
  CGdiexampleDlg::OnAlphaBlend()函数中ColorMatrix的实例ClrMatrix中元?4,4)的gؓ0.5Q表CAlpha度的gؓ0.5(卛_透明)。在ColorMatrix中,元素(5,5)的值恒定ؓ1.0。我们把ClrMatrix的元?0,0)修改?.0Q即使得囑փ2.jpg的红色维度全不显C,再看效果Qؓ?。列位读者,我们以前在豪杰超U解怸调整RQGQBg而控制图像输出颜色的时候,调的是q个东东Q图9的效果很像破旧彩色电视机Q红色电子枪"?了。刚大学毕业Ӟ俺那个叫I啊Q就Cq么个电视机Q还看得很爽Q真是往事不堪回首!

WindowsGDI和GDI+~程实例全剖?6)
? GDI+中的ColorMatrix

强大的文字输?br />
  GDI+拥有极其强大的文字输出处理能力,输出文字的颜艌Ӏ字体、填充方式都可以直接作ؓGraphicscDrawString成员函数的参数进行设|,其功能远胜过GDI讑֤上下文的TextOut函数?br />

void CGdiexampleDlg::OnText()
{
 // TODO: Add your command handler code here
 CClientDC dc(this);
 //创徏Graphics对象
 Graphics graphics(dc);
 //创徏20?楷体"字体
 FontFamily fontFamily1(L "楷体_GB2312"); // 定义"楷体"字样
 Font font1(&fontFamily1, 20, FontStyleRegular, UnitPoint);
 //定义输出UNICODE字符?br /> WCHAR string[256];
 wcscpy(string, L "天极|的读者朋友,您好Q?);
 //以蓝色画刷和20?楷体"昄字符?br /> graphics.DrawString(string, (INT)wcslen(string), &font1, PointF(30, 10),&SolidBrush(Color::Blue));
 //定义字符串显C画?br /> LinearGradientBrush linGrBrush(Point(30, 50), Point(100, 50), Color(255, 255,0, 0), Color(255, 0, 0, 255));
 //以线性渐变画刷和创徏?0?楷体"昄字符?br /> graphics.DrawString(string, (INT)wcslen(string), &font1, PointF(30, 50),&linGrBrush);
 //创徏20?华文行楷"字体
 FontFamily fontFamily2(L "华文行楷"); // 定义"楷体"字样
 Font font2(&fontFamily2, 20, FontStyleRegular, UnitPoint);
 //以线性渐变画刷和20?华文行楷"昄字符?br /> graphics.DrawString(string, (INT)wcslen(string), &font2, PointF(30, 90),&linGrBrush);
 //以图像创建画?br /> Image image(L "d:\3.jpg");
 TextureBrush tBrush(&image);
 //以图像画刷和20?华文行楷"昄字符?br /> graphics.DrawString(string, (INT)wcslen(string), &font2, PointF(30, 130),&tBrush);
 //创徏25?华文中宋"字体
 FontFamily fontFamily3(L "华文中宋"); // 定义"楷体"字样
 Font font3(&fontFamily2, 25, FontStyleRegular, UnitPoint);
 //以图像画刷和20?华文行楷"昄字符?br /> graphics.DrawString(string, (INT)wcslen(string), &font3, PointF(30, 170),&tBrush);
}

  上述代码的执行效果如?0所C,字体、颜色和填充都很丰富Q?br />

David Lee 2009-02-07 19:37 发表评论
]]>错误 警告 d宣判大会http://www.shnenglu.com/Lee/archive/2008/12/19/69828.htmlDavid LeeDavid LeeFri, 19 Dec 2008 05:52:00 GMThttp://www.shnenglu.com/Lee/archive/2008/12/19/69828.htmlhttp://www.shnenglu.com/Lee/comments/69828.htmlhttp://www.shnenglu.com/Lee/archive/2008/12/19/69828.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/69828.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/69828.html 1
.Compiler  Warning (level 1)  C4717
warning C4717: 'CTestView::OnCreate' : recursive on all control paths, function will cause runtime stack overflow//本h遇到
下ؓ|络转蝲Q?br />Error Message
'function' : recursive on allcontrolpaths, functionwillcauseruntimestackoverflow

如下面代码:
#include "wingdi.h"

HPEN Graphics::CreatePen( int penStyles /*= PS_SOLID*/, COLORREF penCol /*= RGB(255, 255, 255)*/, int thickness /*= 1*/ )
{
HPEN ahPen = CreatePen(penStyles, thickness, penCol);
return ahPen;
}

q样在编译的时候,~译器会提示warningC4717: 'GDIEngine::Graphics::CreatePen' : recursive on allcontrolpaths, functionwillcauseruntimestackoverflow

Dq样问题的原因是Q编译器不知道HPEN ahPen = CreatePen(penStyles, thickness, penCol);调用的CreatePen是哪一个?br />
解决问题Q?br />HPEN Graphics::CreatePen( int penStyles /*= PS_SOLID*/, COLORREF penCol /*= RGB(255, 255, 255)*/, int thickness /*= 1*/ )
{
HPEN ahPen = ::CreatePen(penStyles, thickness, penCol);
return ahPen;
}
 
      

David Lee 2008-12-19 13:52 发表评论
]]>#define WINAPI __stdcall是什么意思(转)http://www.shnenglu.com/Lee/archive/2008/12/09/68966.htmlDavid LeeDavid LeeTue, 09 Dec 2008 10:43:00 GMThttp://www.shnenglu.com/Lee/archive/2008/12/09/68966.htmlhttp://www.shnenglu.com/Lee/comments/68966.htmlhttp://www.shnenglu.com/Lee/archive/2008/12/09/68966.html#Feedback1http://www.shnenglu.com/Lee/comments/commentRss/68966.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/68966.html  函数调用U定有多U,q里单说一下:  
        1、__stdcall调用U定相当?6位动态库中经怋用的PASCAL调用U定。在32位的VC++5.0中PASCAL调用U定不再被支持(实际上它已被定义为__stdcall。除了__pascal外,__fortran和__syscall也不被支持)Q取而代之的是__stdcall调用U定。两者实质上是一致的Q即函数的参数自叛_左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,但不同的是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明Q? 
          _stdcall是PascalE序的缺省调用方式,通常用于Win32   Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC函数编译后会在函数名前面加上下划线前缀Q在函数名后加上"@"和参数的字节数? 
          2、C调用U定Q即用__cdecl关键字说明)按从双左的序压参数入栈,p用者把参数弹出栈。对于传送参数的内存栈是p用者来l护的(正因为如此,实现可变参数的函数只能用该调用U定Q。另外,在函数名修饰U定斚w也有所不同? 
          _cdecl是C和CQ+E序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以生的可执行文件大会比调用_stdcall函数的大。函数采用从叛_左的压栈方式。VC函数编译后会在函数名前面加上下划线前缀。是MFC~省调用U定? 
          3、__fastcall调用U定是“h”如其名Q它的主要特点就是快Q因为它是通过寄存器来传送参数的Q实际上Q它用ECX和EDX传送前两个双字QDWORDQ或更小的参敎ͼ剩下的参C旧自叛_左压栈传送,被调用的函数在返回前清理传送参数的内存栈)Q在函数名修饰约定方面,它和前两者均不同? 
          _fastcall方式的函数采用寄存器传递参敎ͼVC函数编译后会在函数名前面加?@"前缀Q在函数名后加上"@"和参数的字节数?         
          4、thiscall仅仅应用于“C++”成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定? 
          5、naked   call采用1-4的调用约定时Q如果必要的话,q入函数时编译器会生代码来保存ESIQEDIQEBXQEBP寄存器,退出函数时则生代码恢复这些寄存器的内宏Vnaked   call不生这L代码。naked   call不是cd修饰W,故必d_declspec共同使用? 
          关键?  __stdcall、__cdecl和__fastcall可以直接加在要输出的函数前,也可以在~译环境的Setting...\C/C++   \Code   Generationw择。当加在输出函数前的关键字与~译环境中的选择不同Ӟ直接加在输出函数前的关键字有效。它们对应的命o行参数分别ؓ/Gz?Gd?Gr。缺省状态ؓ/GdQ即__cdecl? 
          要完全模仿PASCAL调用U定首先必须使用__stdcall调用U定Q至于函数名修饰U定Q可以通过其它Ҏ模仿。还有一个值得一提的是WINAPI宏,Windows.h支持该宏Q它可以出函数译成适当的调用约定,在WIN32中,它被定义为__stdcall。用WINAPI宏可以创qAPIs。?img src ="http://www.shnenglu.com/Lee/aggbug/68966.html" width = "1" height = "1" />

David Lee 2008-12-09 18:43 发表评论
]]>
E序、进E和U程http://www.shnenglu.com/Lee/archive/2008/11/19/67278.htmlDavid LeeDavid LeeWed, 19 Nov 2008 06:11:00 GMThttp://www.shnenglu.com/Lee/archive/2008/11/19/67278.htmlhttp://www.shnenglu.com/Lee/comments/67278.htmlhttp://www.shnenglu.com/Lee/archive/2008/11/19/67278.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/67278.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/67278.html E序 Q是计算机指令的集合Q它以文件的形式存储在磁盘上?br />
q程Q?/font>通常被定义ؓ一个正在运行的E序的实例,是一个程序在其自w的地址I间中的一ơ执行活动?br />
q程是资源申诗调度和独立q行的单位,因此Q它试用pȝ中的q行资源Q?br />而程序不能申Ll资源,不能被系l调度,也不能作为独立运行的单位Q因此它不占用系l资源?br />
q程?部分l成Q?br />1.内核对象          操作pȝ用来理q程的内核对象。 ?内核对象也就是系l用来存放有兌E的l计信息的地斏V?br />2.地址I间          地址I间包含所有可执行模块或DLL模块的代码和数据Q还包含动态内存分配的I间。?br />                              比如Q线E堆栈和堆分配空?br />
q程从来不执行Q何东西,它只是线E的容器?br />若要使它完成某项操作Q它必须拥有一个在它环境里q行的线E,此线E负责执行包含在q程的地址I间中的代码?br />
单个q程可能包含若干U程Q这些线E都是“同时”执行进E地址I间中的代码?br />
每个q程臛_拥有一个线E,来执行地址I间中的代码?br />当创Z个进E时Q系l会自动创徏q个q程的第一个线E,此线E称ZU程?br />此后Q主U程再创建其它线E?br />
q程地址I间Q?br />
pȝ赋予每个q程独立的虚拟地址I间?br />对于32位进E来_q个地址I间是4GB?br />
每个q程都有它的U有地址I间?br />q程A可能有一个存攑֜A的地址I间中的数据l构Q地址?x12345678Q?br />q程B有一个完全不同的数据l构存放在B的地址I间Q地址?x12345678;
当进EA的线E访问地址?x12345678的内存时Q这些线E访问的是进EA的数据结构;
当进EB的线E访问地址?x12345678的内存时Q这些线E访问的是进EB的数据结构;
q程A的线E不能访问进EB的地址I间中的数据l构Q反之亦然?br />
4GB是虚拟内存地址Q只是内存地址的一个范围?br />在你能成功访问数据而不会出现非法访问之前,必须赋予物理寄存器、或者将物理存储器映到各个部分的地址I间?br />
4GB虚拟I间地址中,2GB是内核方式分区,供内总码、设备驱动程序、设备I/O高速缓册Ӏ非面内存池的分配和进E页面表{用;
而用h式分Z用的地址I间Uؓ2GBQ这个分区是q程的私有地址I间所在的地方?br />一个进E不能读取、写入、或者以M方式讉Kȝ在该分区的另一个进E的数据?br />对于所有应用程序来_该分区是l护q程的大部分数据的地斏V?br />
U程Q?br />U程?部分l成Q?br />1.U程的内核对象:
操作pȝ用它来对U程实施理?br />内核对象也是pȝ用来存放U程l计信息的地斏V?br />2.U程堆栈Q?br />它用来维护线E在执行代码旉要的所有参数和局部变量?br />
当创建线E时Q系l创Z个线E内核对象?br />该线E内核对象不是线E本w,而是操作pȝ用来理U程的较的数据l果?br />可以线E内核对象视为由关于U程的统计信息组成的一个小型数据结构?br />
U程L在某个进E环境中创徏。系l从q程的地址I间中分配内存,供线E的堆栈使用?br />新线E运行的q程环境与创建线E的环境相同。因此,新线E可以访问进E的内核对象的所有句柄?br />q程中的所有内存和在这个相同进E中的所有其他线E的堆栈?br />q得单个进E的多个U程能够非常Ҏ的相互通信?br />
U程只有一个内核对象和堆栈Q保留的记录很少Q所以所需的内存也很小?br />
因ؓU程需要的开销比进E少Q因此编E中l常用多U程来解决问题,避免开启新的线E?br />

U程q行Q?br />操作pȝ为每个运行线E安排一定的CPU旉——时间片?br />pȝ通过一U@环的方式为线E提供时间片Q每个线E在自己的时间内q行Q因旉片相当短Q?br />所以给用户的感觉就好像多线E在同时q行一栗?br />
如果一台计机有多个CPUQ线E就能真正意义上的同时运行了Q也是真正的多U程了?/font>

互斥对象Q?br />互斥对象属于内核对象Q它能够保U程拥有对单个资源的互斥讉K权?br />
互斥对象包含一个用数量,一个线EID和一个计数器?br />
ID用于标示pȝ中的哪个U程当前拥有互斥对象Q计数器用于指明该线E拥有互斥对象的ơ数?br />


David Lee 2008-11-19 14:11 发表评论
]]>
析C++里面的宏(转帖)http://www.shnenglu.com/Lee/archive/2008/11/11/66589.htmlDavid LeeDavid LeeTue, 11 Nov 2008 03:31:00 GMThttp://www.shnenglu.com/Lee/archive/2008/11/11/66589.htmlhttp://www.shnenglu.com/Lee/comments/66589.htmlhttp://www.shnenglu.com/Lee/archive/2008/11/11/66589.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/66589.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/66589.html  说到宏,恐怕大安能说出点东西来:一U预处理Q没有分P真的吗?Q。然后呢Q?br />  ?......茫然?.....
  好吧Q我们就从这开始说赗?br />  最常见的宏恐怕是#include了,其次是#defineq有.......
  q是从宏的用途分cdQ?br />  1?include 主要用于包含引用文gQ至今其C无h能替代;
  2、注释掉代码。例如:
   #if 0
   .......
   #endif;
   q种机制是目前注释掉代码的最佳选择Qؓ摩托|拉公司员工所普遍采用Q?br />  3、代码版本管理。例如:
   #ifdef DEBUG
   file://?/a>试版?br />   #else
  
file://?/a>调试版本
   #endif;
  4、声明宏。例如:
   #define DECLARE_MESSAGE(x) x();~x()
file://?/a>没有分号Q哈?br />   //........
   class A
   {
   public:
   DECLARE_MESSAGE(A);
   ..............
   }
   惌v什么了Q呵呵:Q对,VC里面有好多这L东东Q有I我会写《我的VC历程》,?br />  时候会把VC里的各种宏详l的解释一下,那可是一个庞大的工程Q)
  5、符号常量。例如:
   #define PI 3.14159
  6、内联函数。例如:
   #define CLEAR(x) ((x)=0)
  7、泛型函数。例?
   #define ABS(x) ((x)>0? (x):-(x))
   x=3 没问题! x=1.3 也没问题Q?br />   如果是这样呢:
   #include <iostream.h>
   #define A(x) ((x)>0? (x):-(x))
   void main()
   {
  int i=-1;
  cout<<A(1)<<endl;
  cout<<A(++i)<<endl;
   }
   有问题了Q不q以后再_大概讲const or inline 时会说的Q)
  8、泛型类型。例如:
   #define Stack(T) Stack__ ##T
   #define Stackdeclare(T) class Stack(T) {.....}
   Stackdeclare(int);
   Stackdeclare(char);
   .......
   Stack(int) s1;
   Stack(char) s2;
  9、语法扩展。例如:
   Set<int> s;//假设SetZ个描q集合的c?br />   int i;
   FORALL(i,s);
   .......
   宏最大的问题便是易引起冲H,例如Q?br />   libA.h:
   #define MACRO stuff
   同时Q?br />   libB.h:
   #define MACRO stuff
   下面我们对他们进行引用:
   user.cpp:
   #include "libA.h"
   #include "libB.h"
   .............
   p糕Q出C重定义!
   q有一U冲H的可能Q?br />   libB.h:Q没有定义宏MACRO)
   class x { void MACRO(); ...........};
   那么E序q行期间QlibA.h中的宏讲会改变libB.h中的成员函数的名字,D不可预料
  的结果?br />   宏的另一个问题,便是?中出现的问题Q如果你?中的x设ؓ'a'Q程序也不会l出?br />  何警告,所以他是不安全的?br />   针对以上的问题,我们_
   1、尽可能的少用公用宏,能替换掉替换掉Q?br />   2、对那些不能替换的宏Q用命名约定;
   1、符号常量预处理E序我们可以用const or enum 来代替:
   const int TABLESIZE=1024;
   enum { TABLESIZE=1024 }Q?br />   2、非泛型内联函数的预处理E序可以使用真正的内联函数来代替Q?br />   inline void clear(int& x) {x=0;}
   奥,对了Q还有这样一U情况:
   #define CONTROL(c) ((c)-64)
   ..........
   switch(c)
   {
   case CONTROL('a') : ......
   case CONTROL('b') : ......
   case CONTROL('c') : ......
   case CONTROL('d') : ......
   ..........
   }
   q时候就不能单独使用内联函数来取代了Q因为case标签止函数调用Q我们只?br />  做如下{换:
   inline char control(char c) { return c+64; }
   ...........
   switch(control(c))
   {
   case 'a':.....
   case 'b':.....
   case 'c':.....
   case 'd':.....
   ........
   }
   当然q样做是以牺牲时间作ZLQ你xZ?)Q?br />   3、对于泛型预处理E序Q我们可以用函数模板或类默板来代替:
   template<class T>
   T ABS(const T& t) { return t>0 ? t : -t; }
   template<class T>
   Class Stack { ............ };
   4、最后对于语法扩展程序几乎都可以用一个或多个C++cM替:
   Set<int> s;
   int i;
   Set_iter<int> iter(s);
   while(iter.next(i))
   ...........
   与用宏相比Q我们只是牺牲了一点程序的z性而已?br />   当然q不是所有的宏都能替换(我们也ƈ不主张替换掉所有的宏!Q,对于不能替换?br />  宏,我们应该对他们实行命名约定,例如Q?br />   #define COMPANY_XYZ_LIBABC_MACRO stuff
   同时我们也要采取一定的ҎQ进行预Ԍ
   #ifndef COMPANY_XYZ_LIBABC_MACRO
   #define COMPANY_XYZ_LIBABC_MACRO stuff
   #endif
   当然Q在E序库实现内部定义的宏没有这个约束:
   my.cpp:
   #define MACRO stuff
   ........
   我们l出几个常见的宏Q?
   #define A(x) T_##x
   #define Bx) #@x
   #define Cx) #x
   我们假设Qx=1Q则有:
   A(1)=======T_1
   B(1)======'1'
   C(1)======"1"
   q有一个比较常见的宏:_T
   TCHAR tStr[] = _T("t code");
   _T宏的作用是转换成TCHAR?/div>

David Lee 2008-11-11 11:31 发表评论
]]>
Structure and Union有什么区别?(?http://www.shnenglu.com/Lee/archive/2008/10/20/64491.htmlDavid LeeDavid LeeMon, 20 Oct 2008 06:39:00 GMThttp://www.shnenglu.com/Lee/archive/2008/10/20/64491.htmlhttp://www.shnenglu.com/Lee/comments/64491.htmlhttp://www.shnenglu.com/Lee/archive/2008/10/20/64491.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/64491.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/64491.html阅读全文

David Lee 2008-10-20 14:39 发表评论
]]>
计算a——(资料性质Q?/title><link>http://www.shnenglu.com/Lee/archive/2008/10/20/64450.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Sun, 19 Oct 2008 18:13:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2008/10/20/64450.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/64450.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2008/10/20/64450.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/64450.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/64450.html</trackback:ping><description><![CDATA[ <span style="FONT-SIZE: 9pt"> <font size="4">  计算aQ计机语言通常是一个能完整、准和规则地表达h们的意图<span lang="EN-US">,</span>q用以指挥或控制计算机工作的“符Ll”?span lang="EN-US"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span></font> </span> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  <span style="COLOR: red">计算a通常分ؓ三类Q即机器语言Q汇~语a和高U语a?/span> Q了解内容一Q?/font> <span lang="EN-US"> <br /> <br /> </span> <font size="4">  <span lang="EN-US">1. </span>机器语言</font> <span lang="EN-US"> <br /> </span> <font size="4">   机器语言是用二进制代码表C的计算直接识别和执行的一U机器指令的集合。它是计机的设计者通过计算机的gl构赋予计算机的操作功能。机器语ah灉|、直接执行和速度快等特点?/font> <span lang="EN-US"> <br /> </span> <font size="4">   用机器语a~写E序<span lang="EN-US">,</span>~程人员要首先熟记所用计机的全部指令代码和代码的涵义。手~程序时<span lang="EN-US">,</span>E序员得自己处理每条指o和每一数据的存储分配和输入输出<span lang="EN-US">,</span>q得C~程q程中每步所使用的工作单元处在何U状态。这是一件十分繁琐的工作<span lang="EN-US">,</span>~写E序p的时间往往是实际运行时间的几十倍或几百倍。而且<span lang="EN-US">,</span>~出的程序全是些<span lang="EN-US">0</span>?span lang="EN-US">1</span>的指令代?span lang="EN-US">,</span>直观性差<span lang="EN-US">,</span>q容易出错。现?span lang="EN-US">,</span>除了计算机生产厂家的专业人员?span lang="EN-US">,</span>l大多数E序员已l不再去学习机器语言了?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  <span lang="EN-US">2.</span>汇编语言</font> <span lang="EN-US"> <br /> </span> <font size="4">   Z克服机器语言难读、难~、难记和易出错的~点<span lang="EN-US">,</span>Zq与代码指令实际含义相q的英文~写词、字母和数字{符h取代指o代码<span lang="EN-US">(</span>如用<span lang="EN-US">ADD</span>表示q算W号“+”的机器代码<span lang="EN-US">),</span>于是׃生了汇编语言。所以说<span lang="EN-US">,</span>汇编语言是一U用助记W表C的仍然面向机器的计机语言。汇~语a亦称W号语言。汇~语a由   于是采用了助记符h~写E序<span lang="EN-US">,</span>比用机器语言的二q制代码~程要方便些<span lang="EN-US">,</span>在一定程度上化了~程q程。汇~语a的特Ҏ用符号代替了机器指o代码<span lang="EN-US">,</span>而且助记W与指o代码一一对应<span lang="EN-US">,</span>基本保留了机器语a的灵zL。用汇~语a能面向机器ƈ较好地发挥机器的Ҏ?span lang="EN-US">,</span>得到质量较高的程序?/font> <span lang="EN-US"> <br /> </span> <font size="4">   汇编语言中由于用了助记W号<span lang="EN-US">,</span>用汇~语a~制的程序送入计算?span lang="EN-US">,</span>计算Z能象用机器语a~写的程序一L接识别和执行<span lang="EN-US">,</span>必须通过预先攑օ计算机的“汇~程序“的加工和翻?span lang="EN-US">,</span>才能变成能够被计机识别和处理的二进制代码程序。用汇编语言{非机器语言书写好的W号E序U源E序<span lang="EN-US">,</span>q行时汇~程序要源E序译成目标程序。目标程序是机器语言E序<span lang="EN-US">,</span>它一l被安置在内存的预定位置?span lang="EN-US">,</span>p被计机?span lang="EN-US">CPU</span>处理和执行?/font> <span lang="EN-US"> <br /> </span> <font size="4">   汇编语言像机器指令一?span lang="EN-US">,</span>是硬件操作的控制信息<span lang="EN-US">,</span>因而仍然是面向机器的语a<span lang="EN-US">,</span>使用hq是比较J琐Ҏ<span lang="EN-US">,</span>通用性也差。汇~语a是低U语a。但?span lang="EN-US">,</span>汇编语言用来~制pȝ软g和过E控制Y?span lang="EN-US">,</span>其目标程序占用内存空间少<span lang="EN-US">,</span>q行速度?span lang="EN-US">,</span>有着高语言不可替代的用途?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  <span lang="EN-US">3.</span>高语言</font> <span lang="EN-US"> <br /> </span> <font size="4">   不论是机器语aq是汇编语言都是面向g的具体操作的Q语aҎ器的q分依赖Q要求用者必dgl构及其工作原理都十分熟悉,q对非计机专业人员是难以做到的<span lang="EN-US">,</span>对于计算机的推广应用是不利的。计机事业的发?span lang="EN-US">,</span>促Zd求一些与人类自然语言相接q且能ؓ计算机所接受的语意确定、规则明、自然直观和通用易学的计机语言。这U与自然语言相近qؓ计算机所接受和执行的计算aU高U语a。高U语a是面向用L语言。无ZU机型的计算?span lang="EN-US">,</span>只要配备上相应的高语言的编译或解释E序<span lang="EN-US">,</span>则用该高U语a~写的程序就可以通用?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <font size="4"> <span style="FONT-SIZE: 9pt; COLOR: red">  目前被广泛用的高语言?span lang="EN-US">BASIC</span>?span lang="EN-US">PASCAL</span>?span lang="EN-US">C</span>?span lang="EN-US">COBOL</span>?span lang="EN-US">FORTRAN</span>?span lang="EN-US">LOGO</span>以及<span lang="EN-US">VC</span>?span lang="EN-US">VB</span>{。这些语a都是属于pȝ软g。 </span> <span style="FONT-SIZE: 9pt">Q了解内容二Q?span lang="EN-US"><o:p></o:p></span></span> </font> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  计算机ƈ不能直接地接受和执行用高U语a~写的源E序<span lang="EN-US">,</span>源程序在输入计算机时<span lang="EN-US">,</span>通过“翻译程序”翻译成机器语言形式的目标程?span lang="EN-US">,</span>计算机才能识别和执行。这U“翻译”通常有两U方?span lang="EN-US">,</span>即编译方式和解释方式。编译方式是Q事先编好一个称为编译程序的机器语言E序<span lang="EN-US">,</span>作ؓpȝ软g存放在计机?span lang="EN-US">,</span>当用L高语言~写的源E序输入计算机后<span lang="EN-US">,</span>~译E序便把源程序整个地译成用机器语言表示的与之等L目标E序<span lang="EN-US">,</span>然后计算机再执行该目标程?span lang="EN-US">,</span>以完成源E序要处理的q算q取得结果。解释方式是Q源E序q入计算机时<span lang="EN-US">,</span>解释E序Ҏ描边解释作逐句输入逐句译<span lang="EN-US">,</span>计算Z句句执行<span lang="EN-US">,</span>q不产生目标E序?span lang="EN-US">PASCAL</span>?span lang="EN-US">FORTRAN</span>?span lang="EN-US">COBOL</span>{高U语a执行~译方式<span lang="EN-US">;BASIC</span>语言则以执行解释方式Z<span lang="EN-US">;</span>?span lang="EN-US">PASCAL</span>?span lang="EN-US">C</span>语言是能书写~译E序的高U程序设计语a?每一U高U?span lang="EN-US">(</span>E序设计<span lang="EN-US">)</span>语言<span lang="EN-US">,</span>都有自己Zؓ规定的专用符受英文单词、语法规则和语句l构<span lang="EN-US">(</span>书写格式<span lang="EN-US">)</span>。高U语a与自然语a<span lang="EN-US">(</span>p<span lang="EN-US">)</span>更接q?span lang="EN-US">,</span>而与g功能相分?span lang="EN-US">(</span>dq了具体的指opȝ<span lang="EN-US">),</span>便于q大用户掌握和用。高U语a的通用性强<span lang="EN-US">,</span>兼容性好<span lang="EN-US">,</span>便于UL。下面介l几U较有代表性的高E序设计语言Q?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  ?span lang="EN-US">BASIC</span>语言</font> <span lang="EN-US"> <br /> </span> <font size="4">  <span lang="EN-US">BASIC</span>语言全称?span lang="EN-US">Beginner</span>?span lang="EN-US">s all Purpose Symbolic Instruction Code,</span>意ؓ“初学者通用W号指o代码“?span lang="EN-US">1964</span>q由国辑ְ摩斯学院的基c_和科茨完成设计ƈ提出?span lang="EN-US">BASIC</span>语言的第一个版?span lang="EN-US">,</span>l过不断丰富和发?span lang="EN-US">,</span>现已成ؓ一能全U功面的中小型计机语言?span lang="EN-US">BASIC</span>易学、易懂、易记、易?span lang="EN-US">,</span>是初学者的入门语言<span lang="EN-US">,</span>也可以作为学习其他高语a的基?span lang="EN-US">BASIC</span>有解释方式和~译方式两种译E序?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  ?span lang="EN-US">PASCAL</span>语言</font> <span lang="EN-US"> <br /> </span> <font size="4">  <span lang="EN-US">PASCAL</span>是一U结构程序设计语a<span lang="EN-US">,</span>q士苏黎世联邦工业大学的沃?span lang="EN-US">(<span id="6661616" class="SpellE">N.Wirth</span>)</span>教授研制<span lang="EN-US">,</span>?span lang="EN-US">1971</span>q正式发表。是?span lang="EN-US">ALGOL60</span>衍生?span lang="EN-US">,</span>但功能更ZҎ使用。目?span lang="EN-US">,</span>作ؓ一个能高效率实现的实用语言和一个极好的教学工具<span lang="EN-US">,PASCAL</span>语言在高校计机软g教中学一直处于主导地位?span lang="EN-US">Pascal(<span id="1661111" class="SpellE">B.Pascal</span>)</span>是十七世U法国著名数学家<span lang="EN-US">,</span>他于<span lang="EN-US">1642</span>q曾发明C台式计算机的雏型机—加减法计算机?/font> <span lang="EN-US"> <br /> </span> <font size="4">  <span lang="EN-US">PASCAL</span>h大量的控制结?span lang="EN-US">,</span>充分反映了结构化E序设计的思想和要?span lang="EN-US">,</span>直观易懂<span lang="EN-US">,</span>使用灉|<span lang="EN-US">,</span>既可用于U学计算<span lang="EN-US">,</span>又能用来~写pȝ软g<span lang="EN-US">,</span>应用范日围益q泛?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  ⑉用~程语言</font> <font size="4"> <span lang="EN-US">C<br /></span>  <span lang="EN-US">C</span>语言是美?span lang="EN-US">AT&T</span>与电?span lang="EN-US">) (</span>甉|公司Z实现<span lang="EN-US">UNIX</span>pȝ的设计思想而发展v来的语言工具?span lang="EN-US">C</span>语言的主要特色是兼顾了高U语a和汇~语a的特?span lang="EN-US">,</span>z、丰富、可UL。相当于其他高语言子程序的函数?span lang="EN-US">C</span>语言的补?span lang="EN-US">,</span>每一个函数解决一个大问题中的Q?span lang="EN-US">,</span>函数使程序模块化?span lang="EN-US">C</span>语言提供了结构式~程所需要的各种C化的控制l构?/font> <span lang="EN-US"> <br /> </span> <font size="4">  <span lang="EN-US">C</span>语言是一U通用~程语言<span lang="EN-US">,</span>正被来多的计机用户所推崇。用E语言~写E序<span lang="EN-US">,</span>既感觉到使用高语言的自?span lang="EN-US">,</span>也体会到利用计算机硬件指令的直接<span lang="EN-US">,</span>而程序员却无需卷入汇编语言的繁琐?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  ?span lang="EN-US">COBOL</span>语言</font> <span lang="EN-US"> <br /> </span> <font size="4">  <span lang="EN-US">COBOL</span>的全U是<span lang="EN-US">Common Business Oriented Language,</span>意即Q通用商业语言?/font> <span lang="EN-US"> <br /> </span> <font size="4">  在企业管理中<span lang="EN-US">,</span>数Dƈ不复?span lang="EN-US">,</span>但数据处理信息量却很大。ؓ专门解决l企理问题<span lang="EN-US">,</span>?span lang="EN-US">1959</span>q?span lang="EN-US">,</span>q国的一些计机用户l织设计了专用于商务处理的计机语言<span lang="EN-US">COBOL,</span>q于<span lang="EN-US">1961</span>q美国数据系l语a协会公布。经不断修改、丰富完善和标准?span lang="EN-US">,</span>已发展ؓ多种版本?/font> <span lang="EN-US"> <br /> </span> <font size="4">  <span lang="EN-US">COBOL</span>语言使用?span lang="EN-US">300</span>多个p保留?span lang="EN-US">,</span>大量采用普通英语词汇和句型<span lang="EN-US">,COBOL</span>E序通俗易懂<span lang="EN-US">,</span>素有“英语语a”之U?/font> <span lang="EN-US"> <br /> </span> <font size="4">  <span lang="EN-US">COBOL</span>语言语法规则严格。用<span lang="EN-US">COBOL</span>语言~写的Q一源程?span lang="EN-US">,</span>依都要次按标识部、环境部、数据部和过E部四部分书?span lang="EN-US">,COBOL</span>E序l构的“部”内包含“节?span lang="EN-US">,</span>“节”内包含“段?span lang="EN-US">,</span>D内包含语句<span lang="EN-US">,</span>语句由字或字W串l成<span lang="EN-US">,</span>整个源程序象一는根到q?span lang="EN-US">,</span>由干到枝<span lang="EN-US">,</span>由枝到叶的树<span lang="EN-US">,</span>习惯上称之ؓ树型l构?/font> <span lang="EN-US"> <br /> </span> <font size="4">  目前<span lang="EN-US">COBOL</span>语言主要应用于情报检索、商业数据处理等理领域?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  常用的高U程序设计语a<span lang="EN-US">,</span>除了上述的几U之?span lang="EN-US">,</span>q有很多<span lang="EN-US">,</span>如以英国著名诗h拜u<span lang="EN-US">(<span id="6116111" class="SpellE">G.N.G.Byron</span>)</span>的独生女艾达·拜u<span lang="EN-US">(<span id="1166611" class="SpellE">Ada</span> Byron)</span>的名字命名的军用语言<span id="1616166" class="SpellE"><span lang="EN-US">Ada</span></span><span lang="EN-US">,</span>深受中、小学生Ƣ迎的语a<span lang="EN-US">LOGO</span>{等?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <p> <span style="FONT-SIZE: 9pt"> <font size="4">  目前<span lang="EN-US">,</span>E序设计语言及编E环境正向面向对象语a及可视化~程环境方向发展<span lang="EN-US">,</span>出现了许多第四代语言及其开发工兗如Q微软公?span lang="EN-US">(Microsoft)</span>开发的<span lang="EN-US">Visual</span>pd<span lang="EN-US">(VC++</span>?span lang="EN-US">VB</span>?span lang="EN-US">FoxPro)</span>~程?/font> <span lang="EN-US"> <?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /?> <v:shapetype id="_x0000_t75" path=" m@4@5 l@4@11@9@11@9@5 xe" stroked="f" filled="f" o:spt="75" o:preferrelative="t" coordsize="21600,21600"> <font size="4"> <v:stroke joinstyle="miter"> </v:stroke> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0 "> </v:f> <v:f eqn="sum @0 1 0 "> </v:f> <v:f eqn="sum 0 0 @1 "> </v:f> <v:f eqn="prod @2 1 2 "> </v:f> <v:f eqn="prod @3 21600 pixelWidth "> </v:f> <v:f eqn="prod @3 21600 pixelHeight "> </v:f> <v:f eqn="sum @0 0 1 "> </v:f> <v:f eqn="prod @6 1 2 "> </v:f> <v:f eqn="prod @7 21600 pixelWidth "> </v:f> <v:f eqn="sum @8 21600 0 "> </v:f> <v:f eqn="prod @7 21600 pixelHeight "> </v:f> <v:f eqn="sum @10 21600 0 "> </v:f> </v:formulas> <v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"> </v:path> <o:lock v:ext="edit" aspectratio="t"> </o:lock> </font> </v:shapetype> <v:shape id="_x0000_i1032" style="WIDTH: 12pt; HEIGHT: 12pt" coordsize="21600,21600" type="#_x0000_t75"> <v:imagedata src="yuyan.files/image001.png" o:title=""> </v:imagedata> </v:shape> </span> <font size="4">具及<span lang="EN-US">Power Builder</span>{?span lang="EN-US">,</span>目前已经在国内外得到了广泛的应用?span lang="EN-US"><o:p></o:p></span></font> </span> </p> <img src ="http://www.shnenglu.com/Lee/aggbug/64450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2008-10-20 02:13 <a href="http://www.shnenglu.com/Lee/archive/2008/10/20/64450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC框架关系?/title><link>http://www.shnenglu.com/Lee/archive/2008/09/21/62376.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Sat, 20 Sep 2008 16:21:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2008/09/21/62376.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/62376.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2008/09/21/62376.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/62376.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/62376.html</trackback:ping><description><![CDATA[ <p> <img height="686" src="file:///C:/Documents%20and%20Settings/Administrator/桌面/59_36494_7602cdbb3156f36.jpg" width="539" /> </p> <img src ="http://www.shnenglu.com/Lee/aggbug/62376.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2008-09-21 00:21 <a href="http://www.shnenglu.com/Lee/archive/2008/09/21/62376.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习VC MFC开发必M解的常用宏和指ohttp://www.shnenglu.com/Lee/archive/2008/09/19/62305.htmlDavid LeeDavid LeeFri, 19 Sep 2008 12:56:00 GMThttp://www.shnenglu.com/Lee/archive/2008/09/19/62305.htmlhttp://www.shnenglu.com/Lee/comments/62305.htmlhttp://www.shnenglu.com/Lee/archive/2008/09/19/62305.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/62305.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/62305.html 1、#include指o  
包含指定的文件 ?/font>

2?define指o   
预定?通常用它来定义常?包括无参量与带参?Q以及用来实现那些“表面似和善、背后一长串”的宏,它本wƈ不在~译q程中进行,而是在这之前(预处理过E?已l完成了

3?typedef指o
常用来定义一个标识符及关键字的别名它是语a~译q程的一部分Q但它ƈ不实际分配内存空间?

4?ifndef   #else   #endif指o  
条g~译。一般情况下Q源E序中所有的行都参加~译。但是有时希望对其中一部分内容只在满一定条件才q行~译Q也是对一部分内容指定~译的条Ӟq就是“条件编译”。有Ӟ希望当满x条g时对一l语句进行编译,而当条g不满x则编译另一l语句。 ?br />条g~译命o最常见的Ş式ؓQ ?br />#ifdef 标识W ?br />   E序D?
#else
   E序D?  
#endif  
它的作用是:当标识符已经被定义过(一般是?define命o定义)Q则对程序段1q行~译Q否则编译程序段2?

5?Pragma 指o  
在所有的预处理指令中Q?Pragma 指o可能是最复杂的了Q它的作用是讑֮~译器的状态或者是指示~译器完成一些特定的动作。其格式一般ؓ  
#Pragma Para  
其中Para 为参敎ͼ下面来看一些常用的参数?
l          message 参数。它能够在编译信息输出窗口中输出相应的信息,q对于源代码信息的控制是非常重要的。其使用Ҏ为:  
#Pragma message(“消息文本?  
当编译器遇到q条指o时就在编译输出窗口中消息文本打印出来。 ?br />当我们在E序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设|这些宏Q此时我们可以用q条指o在编译的时候就q行查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86q个宏可以用下面的方?
#ifdef _X86
         #Pragma message(“_X86 macro activated!?
         #endif   
当我们定义了_X86q个宏以后,应用E序在编译时׃在编译输出窗口里昄“_X86 macro activated!”。我们就不会因ؓ不记得自己定义的一些特定的宏而抓x腮了  
l          另一个用得比较多的pragma参数是code_seg。格式如Q?
#pragma code_seg( ["section-name"[,"section-class"] ] )  
它能够设|程序中函数代码存放的代码段Q当我们开发驱动程序的时候就会用到它。 ?br />l          #pragma once  
只要在头文g的最开始加入这条指令就能够保证头文件被~译一ơ,q条指o实际上在VC6中就已经有了Q但是考虑到兼Ҏƈ没有太多的用它。 ?br />l          #pragma hdrstop  
表示预编译头文g到此为止Q后面的头文件不q行预编译。BCB可以预编译头文g以加快链接的速度Q但如果所有头文g都进行预~译又可能占太多盘I间Q所 以用这个选项排除一些头文g。有时单元之间有依赖关系Q比如单元A依赖单元BQ所以单元B要先于单元A~译。你可以?pragma startup?定编译优先Q如果用了#pragma package(smart_init) QBCB׃Ҏ优先U的大小先后~译。 ?br />l          #pragma resource "*.dfm"  
表示?.dfm文g中的资源加入工程?.dfm中包括窗体外观的定义。 ?br />l          #pragma warning( disable : 4507 34; once : 4385; error : 164 )
{h于:  
#pragma warning(disable:4507 34) // 不显C?507?4可告信?
         #pragma warning(once:4385) // 4385可告信息仅报告一?
         #pragma warning(error:164) // ?64可告信息作Z个错误?
同时q个pragma warning 也支持如下格式:
#pragma warning( push [ ,n ] )
#pragma warning( pop )
q里n代表一个警告等U?1---4)?
#pragma warning( push )保存所有警告信息的现有的警告状态?
#pragma warning( push, n)保存所有警告信息的现有的警告状态,q且把全局警告
{讑֮为n?
#pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的
一切改动取消。例如:
#pragma warning( push )
#pragma warning( disable : 4705 )
#pragma warning( disable : 4706 )
#pragma warning( disable : 4707 )
//.......
#pragma warning( pop )
在这D代码的最后,重新保存所有的警告信息(包括4705Q?706?707)?
l          pragma comment(...)
该指令将一个注释记录放入一个对象文件或可执行文件中?
常用的lib关键字,可以帮我们连入一个库文g?
每个~译E序可以?pragma指oȀzLl止该编译程序支持的一些编译功能。例如,对@环优化功能:
#pragma loop_opt(on) // Ȁz?
#pragma loop_opt(off) // l止
有时Q程序中会有些函C使编译器发出你熟知而想忽略的警告,如“Parameter xxx is never used in function xxx”,可以q样Q?
#pragma warn ?00 // Turn off the warning message for warning #100
int insert_record(REC *r)
{ /* function body */ }
#pragma warn +100 // Turn the warning message for warning #100 back on
函数会生一条有唯一特征?00的警告信息,如此可暂时终止该警告?
每个~译器对#pragma的实C同,在一个编译器中有效在别的~译器中几乎无效。可从编译器的文档中查看?

6、宏Q__LINE__   和__FILE__
     定义源程序文件名和代码行Q这对于调试跟踪代码错误行很有帮助?
__TIME__           Q编译时?
__DATE__       Q编译日?
__TIMESTAMP__ Q文件修Ҏ?

7、调试宏QASSERT()、VERIFY()、TRACE()
q三个宏在Debug环境下特别有效,常用于代码的跟踪调试。它们是否v作用取决于是否定义了预定义了?_DEBUG
l          ASSERT
ASSERT(booleanExpression)
说明Q?
计算变量的倹{如果结构的gؓ0Q那么此宏便打印一个诊断消息ƈ且程序运行失败。如果条件ؓ?Q那么什么也不做。诊断消息的形式为: assertion failed in file in line 其中name是元文g名,num是源文g中运行失败的中断受?在Release 版中QASSERT不计表辑ּ的g׃中断E序。如果必计此表达式的g不管环境如何那么用VERIFY代替ASSERT?
q个宏通常原来判断E序中是否出C明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查N误?
ASSERT_VAILD
ASSERT_VAILD(pObject)
说明Q?
用于关于对象的内部状态的有效性。ASSERT_VALID调用此对象的AssertValid成员函数Q把它们作ؓ自己的变量来传递)。在 Release版中ASSERT_VALID什么也不做。在DEBUG版中Q他查指针,以不同于NULL的方式进行检查,q调用对象自q AssertValid成员函数。如果这些检中有Q何一个失败的话,那么他会以与ASSERT相同的方法显CZ个警告的消息?
l          VERIFY
VERIFY(booleanExpression)
说明Q?
在MFC的DEBUG版中QVERIFY宏计它的变量倹{如果结果ؓ0Q那么宏打印一个诊断消息ƈ中止E序。如果条件不?Q那么什么工作也不作。诊?有如下Ş式: assertion failed in file in line 其中name是源文g的名字,num是在源文件中p|的中止行受在 MFC的Release版中QVERIFY计算表达式g不打印或中止E序。例如:如果表达式是个函数调用,那么调用成功?
l          TRACE
TRACE(exp)
说明Q?
把一个格式化字符串送到转储讑֤Q例如,文g或调试监视器Q功能上和printf怼Q可以说是调试环境下printf的一个拷贝。TRACE宏是一?在程序运行时跟踪变量值的方便形式。在DEBUG环境中,TRACE宏输出到afxDump。在Release版中他不做Q何工作。另外还有一l可以带?数的怼的宏QTRACE0、TRACE1、TRACE2和TRACE3。提供格式如Q?
TRACE0(exp)
TRACE1(exp,param1)
TRACE2(exp,param1,param2)
TRACE3(exp,param1,param2,param3)
与TRACE怼Q但它把跟踪字符串放在代码段中,而不是DGROUPQ因此用少的DGROUPI间。这些宏的用法和printfcM?

8、消息处理宏QDECLARE_MESSAGE_MAP 、BEGIN_MESSAGE_MAP、END_MESSAGE_MAP
DECLARE_MESSAGE_MAP()
说明Q?
用户E序中的每个CCmdTargetzcdL供消息映以处理消息。在cd义的末尾使用DECLARE_MESSAGE_MAP宏。接着Q在定义c?成员函数?CPP文g中,使用BEGIN_MESSAGE_MAP宏,每个用户消息处理函数的宏下面的列表以及END_MESSAGE_MAP宏?
注释Q?
如果在DECLARE_MESSAGE_MAP之后定义M一个成员,那么必须Z们指定一个新存取cdQ公qQ私有的Q保护的Q?
BEGIN_MESSAGE_MAP(the class,baseclass)
END_MESSAGE_MAP
说明Q?
使用BEGIN_MESSAGE_MAP开始用h息映的定义。在定义用户cd数的工具Q?cppQ文件中Q以BEGIN_MESSAGE_MAP宏开始消息映,然后为每个消息处理函数增加宏,接着以END_MESSAGE_MAP宏完成消息映?

9、消息映宏QON_COMMAND 、ON_CONTROL、ON_MESSAGE、ON_VBXEVENT?/strong>ON_Update_COMMAND_UI和ON_REGISTERED_MESSAGE
ON_COMMAND(id,memberFxn)
说明Q?
此宏通过ClassWizard或手工插入一个消息映。它表明那个函数从一个命令用h口(例如一个菜单项或toolbar按钮Q处理一个命令消息?当一个命令对象通过指定的ID接受C个Windows WM_COMMAND消息ӞON_COMMAND调用成员函数memberFxn处理此消 息。在用户的消息映中Q对于每个菜单或加速器命oQ必被映射C个消息处理函敎ͼ应该实有一个ON_COMMAND宏语句?
ON_CONTROL(wNotifyCode,id,memberFxn)
说明Q?
表明哪个函数处理一个常规控制表C消息。控制标识消息是那些从一个控制夫发送到母窗口的消息?
ON_MESSAGE(message,memberFxn)
说明Q?
指明哪个函数处理一用户定义消息。用户定义消息通常定义在WM_USER?x7FF范围内。用户定义消息是那些不是标准 Windows WM_MESSAGE消息的Q何消息。在用户的消息映中Q每个必被映射C个消息处理函数。用户定义消息应该有一?ON_MESSAGE宏语句?
ON_Update_COMMAND_UI(idQmemberFxn)
说明Q?
此宏通常通过ClassWizard被插入一个消息映,以指明哪个函数将处理一个用h口个更改命o消息。在用户的消息映中Q每个用h口更改命令(比讯被映到一个消息处理函敎ͼ应该有一个ON_Update_COMMAND_UI宏语句?
ON_VBXEVENT(wNotifyCode,memberFxn)
说明Q?
此宏通常通过ClassWizard被插入一个消息映,以指明哪个函数将处理一个来自VBX控制的消息。在用户的消息映中每个被映到一消息处理函数的VBX控制消息应该有一个宏语句?
ON_REGISTERED_MESSAGE(nmessageVarible,memberFxn)
说明Q?
Windows的RegisterWindowsMesage函数用于定义一个新H口消息Q此消息保证在整个系l中是唯一的。此宏表明哪个函数处理已注册消息。变量nMessageViable应以NEAR修饰W来定义?/font>

10、DEBUG_NEW
#define new DEBUG_NEW
说明Q?
帮助查找内存错误。用户在E序中用DEBUG_NEW,用户通常使用newq算W来从堆上分配。在Debug模式下(但定义了一个DEBUGW号Q, DEBUG_NEW为它分配的每个对象记录文件名和行受然后,在用户用CMemoryState::DumpAllObjectSince成员函数 Ӟ每个以DEBUG_NEW分配的对象分配的地方昄出文件名和行受ؓ了用DEBUG_NEW,应在用户的资源文件中插入以下指oQ?#define new DEBUG_NEW 一旦用h入本指oQ预处理E序在使用new的地Ҏ入DEBUG_NEWQ而MFC作其余的工作。但 用户~译自己的程序的一个发行版ӞDEBUG_NEW便进行简单的new操作Q而且不生文件名和行h息?

11、异常宏QTRY、CATCH 、THROW、AND_CATCH、THROW_LAST和END_CATCH
TRY
说明Q?
使用此宏建立一TRY块。一个TRY识别一个可排除异常的代码块。这些异常在随后的CATCH和AND_CATCH块处理。传递是允许的:异常可以传递一个外部TRY块,或者忽略它们或者用THROW_LAST宏?
CATCH(exception_class,exception_object_pointer_name)
说明Q?
使用此用定义一个代码块Q此代码用来获取当前TRY块中都一个异常类型。异常处理代码可以访问异常对象,如何合适的话,׃得到关于异常的特D原因的更多 消息。调用THROW_LAST宏以把处理过E一下一个外部异常框Ӟ如果exception-class是类CExceptioon,那么会获取所有异 常类型。用户可以用CObject::IsKindOf成员函数以确定那个特别异常被排除。一U获取异常的最好方式是使用序的AND_CATCH?句,每个带一个不同的异常cd。此异常cd的指针由宏定义,用户不必定义?
注释Q?
此CATCH块被定义作一个C++范围Q由花括hqͼ。如用户在此范围定义变量Q那么它们只在吃范围内可以访问。他q可以用于异常对象的指针名?
THROW(exception_object_pointer)
说明Q?
zև指定的异常。THROW中断E序的运行,把控制传递给用户E序中的相关的CATCH块。如果用h有提供CATCH块,那么控制被传递到一个MFC模块Q他打印Z个错误ƈl止q行?
AND_CATCH(exception_class,exception _object_point_name)
说明Q?
定义一个代码块Q它用于获取废除当前TRY块中的附加异常类型。用CATCH宏以获得一个异常类型,然后使用AND_CATCH宏获得随后的异常处理?码可以访问异常对象(若合适的?已得到关于异常的特别原因的更多消息。在AND_CATCH块中调用THROW_LAST宏以便把处理q程Ud下个外部 异常框架。AND_CATCH可标记CATCH或AND_CATCH块的末尾?
注释Q?
AND_CATCH块被定义成ؓ一个C++作用域(p括号来描qͼ。若用户在此作用域定义变量,那么C他们只在此作用域中可以访问。他也用于exception_object_pointer_name变量?
THROW_LAST()
说明Q?
此宏允许用户zև一个局部徏立的异常。如果用戯图排除一个刚发现的异常,那么一般此异常溢出ƈ被删除。用THROW_LAST,此异常被直接传送到下一个CATCH处理E序?
END_CATCH
说明Q?
标识最后的CATCH或AND_CATCH块的末尾?

12、DECLARE_DYNAMIC 、IMPLEMENT_DYNAMIC
DECLARE_DYNAMIC(class_name)
说明Q?
但从CObjectz一个类Ӟ此宏增加关于一个对象类的访问运行时间功能。把DECLARE_DYNAMIC宏加入类的头文g中,然后在全部需要访?此类对象?CPP文g中都包含此模块。如果像所描述那样使用DELCARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,那么用户便可使用 RUNTIME_CLASS宏和CObject::IsKindOf函数以在q行旉军_对象cR如果DECLARE_DYNAMIC包含在类定义中,?么IMPLEMETN_DYNAMIC必须包含在类工具中。 ?br />IMPLEMENT_DYNAMIC(class_name,base_class_name)
说明Q?
通过q行时在串行l构中ؓ动态CObjectzc访问类名和位置来生必要的C++代码。在.CPP文g中用IMPLEMENT_DYNAMIC宏,接着一ơ链接结果对象代?

13、DECLARE_DYNCreate、IMPLEMENT_DYNCreate
DECLARE_DYNCreate(class_name)
说明Q?
使用DECLARE_DYNCRETE宏以便允许CObjectzcȝ对象在运行时刻自动徏立。用此功能自动建立新对象,例如Q但它在串行化过E中?盘M个对象时Q文件及视图和框架窗应该支持动态徏立,因ؓ框架需要自动徏立它。把DECLARE_DYNCreate宏加入类?H文g中,然后在全 部需要访问此cd象的.CPP文g中包含这一模式。如果DECLARE_DYNCreate包含在类定义中,那么IMPLEMENT_DYNCreate 必须包含在类工具中?
IMPLEMENT_DYNCreate(class_name,base_class_name)
说明Q?
通过DECLARE_DYNCreate宏来使用IMPLEMENT_DYNCreate宏,以允许CObjectzcd象在q行时自动徏立。主Z?此功能自动徏立对象,例如Q但它在串行化过E中从磁盘读M个对象时Q他在类工具里加入IMPLEMENT_DYNCreate宏。若用户使用 DECLARE_DYNCreate和IMPLEMENT_DYNCreate?那么接着使用RUNTIME_CLASS宏和CObject:: IsKindOf成员函数以在q行时确定对象类。若declare_dyncreate包含在定义中Q那么IMPLEMENT_DYNCreate必须?含在cd具中?

14、DECLARE_SERIAL、IMPLEMENT_SERIAL
DECLARE_SERIAL(class_name)
说明Q?
DECLARE_SERIALZ个可以串行化的CObjectzcM生必要的C++标题代码。串行化是把某个对象的内容从一个文件读出和写入一文g??H文g中用DECLARE_SERIAL宏,接着在需要访问此cd象的全部.CPP文g中包含此文g。如果DECLARE_SERIAL包含在类?义中Q那么IMPLEMENT_SERIAL必须包含在类工具中。DECLARE_SERIAL宏包含全部DECLARE_DYNAMIC, IMPLEMENT_DYCreate的功能?
IMPLEMENT_SERIAL(class_name,base_class_name,wSchema)
说明Q?
通过q行时在串行l构中动态CObjectzc访问类名和位置来徏立必要的C++代码。在.CPP文g中用IMPLEMENT_SERIAL宏,然后一ơ链接结果对象代码?

15、RUNTIME_CLASS
RUNTIME_CLASS(class_name)
说明Q?
使用此宏从c++cd中获取运行时cȝ构。RUNTIME_CLASS为由class_name指定的类q回一个指针到CRuntimeClassl构?只有以DECLARE_DYNAMIC、DECLARE_DYNCreate或DECLARE_SERIAL定义的CObjectzcLq回C?CRuntimeClassl构的指针?/font>



David Lee 2008-09-19 20:56 发表评论
]]>
MFC应用E序中指针的使用(转帖)http://www.shnenglu.com/Lee/archive/2008/09/19/62236.htmlDavid LeeDavid LeeThu, 18 Sep 2008 17:13:00 GMThttp://www.shnenglu.com/Lee/archive/2008/09/19/62236.htmlhttp://www.shnenglu.com/Lee/comments/62236.htmlhttp://www.shnenglu.com/Lee/archive/2008/09/19/62236.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/62236.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/62236.html2) 在App中获得MainFrame指针
3) 在View中获得MainFrame指针
4) 获得ViewQ已建立Q指?br />5) 获得当前文档指针
6) 获得状态栏与工h指针
7) 获得状态栏与工h变量
8) 在Mainframe获得菜单指针
9) 在Q何类中获得应用程序类
10) 从文档类取得视图cȝ指针(1)
11) 在App中获得文档模板指?br />12) 从文档模板获得文档类指针
13) 在文档类中获得文档模板指?br />14) 从文档类取得视图cȝ指针(2)
15) 从一个视囄取得另一视图cȝ指针

VC中编E对于刚刚开始学习的同学Q最大的障碍和问题就是消息机制和指针获取?br />操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多
问题都能解决。下面文字主要是个h在编E中指针使用的一些体会,说的不当的地
方请指正。一般我们用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架Q?br />无论是多文档q是单文档,都存在指针获取和操作问题。下面这节内容主要是一?br />的框Ӟ然后再讲多线E中的指针用。用到的类需要包含响应的头文件。首?br />一般获得本c?视,文档Q对话框都支?实例指针thisQ用this的目的,主要可以?br />q类中的函数向其他类或者函C发指针,以便于在非本cM操作和用本cM?br />功能?br />
1Q?在View中获得Doc指针 CYouSDIDoc *pDoc=GetDocument();一个视只能有一个文
档?br /> 2) 在App中获得MainFrame指针
CWinApp 中的 m_pMainWnd变量是MainFrame的指?br />也可以: CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();
3) 在View中获得MainFrame指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
4) 获得ViewQ已建立Q指?CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
CyouView *pView=(CyouView *)pMain->GetActiveView();
5) 获得当前文档指针 CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();
6) 获得状态栏与工h指针 CStatusBar * pStatusBarQ?CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);

7) 如果框架中加入工h和状态栏变量q可以这?
(CMainFrame *)GetParent()->m_wndToolBar;
(CMainFrame *)GetParent()->m_wndStatusBar;

8) 在Mainframe获得菜单指针 CMenu *pMenu=m_pMainWnd->GetMenu();
9) 在Q何类中获得应用程序类
用MFC全局函数AfxGetApp()获得?br />
10) 从文档类取得视图cȝ指针
我是从http://download.cqcnc.com/soft/program/article/vc/vc405.html学到的,
从文档获得视囄指针目的一般ؓ了控制同一文档的多个视囄定位问题Q我的体?br />特别是文字处理CEditView当生多个视囄Ӟq个功能是非帔R要的?
CDocumentcL供了两个函数用于视图cȝ定位Q?br />GetFirstViewPosition()和GetNextView()
virtual POSITION GetFirstViewPosition() const;
virtual CView* GetNextView(POSITION& rPosition) const;

注意QGetNextView()括号中的参数用的是引用方式,因此执行后值可能改变?br />GetFirstViewPosition()用于q回W一个视图位|(q回的ƈ非视囄指针Q而是一
个POSITIONcd|QGetNextView()有两个功能:q回下一个视囄的指针以及用
引用调用的方式来改变传入的POSITIONcd参数的倹{很明显Q在TestE序中,只有
一个视囄Q因此只需这两个函数调用一ơ即可得到CTestView的指针如下(需?br />义一个POSITIONl构变量来辅助操作)Q?
CTestView* pTestView;
POSITION pos=GetFirstViewPosition();
pTestView=GetNextView(pos);

q样Q便可到了CTestViewcȝ指针pTestView.执行完几句后Q变量pos=NULL,因ؓ?br />有下一个视囄Q自然也没有下一个视囄的POSITION.但是q几条语句太单,?br />h太强的通用性和安全特征Q当象前面说的那P当要在多个视图ؓ中返回某个指
定类的指针时Q我们需要遍历所有视囄Q直到找到指定类为止。判断一个类指针?br />向的是否某个cȝ实例Ӟ可用IsKindOf()成员函数时行查,如:
pView->IsKindOf(RUNTIME_CLASS(CTestView));
卛_查pView所指是否是CTestViewcR?br />
有了以上基础Q我们已l可以从文档cd得Q何类的指针。ؓ了方便,我们其?br />Z个文档类的成员函敎ͼ它有一个参敎ͼ表示要获得哪个类的指针。实现如下:
CView* CTestDoc::GetView(CRuntimeClass* pClass)
{
CView* pView;
POSITION pos=GetFirstViewPosition();

while(pos!=NULL){
pView=GetNextView(pos);
if(!pView->IsKindOf(pClass))
break;
}

if(!pView->IsKindOf(pClass)){
AfxMessageBox("Connt Locate the View.\r\n http://www.VCKBASE.com");
return NULL;
}

return pView;
}

其中用了两次视图cȝ成员函数IsKindOf()来判断,是因为退出while循环有三U?br />可能Q?br />
1.pos为NULLQ即已经不存在下一个视囄供操作;
2.pView已符合要求?br />
1?同是满。这是因为GetNextView()的功能是当前视图指针改变成一个视?br />的位|同时返回当前视图指针,因此pos是pView的下一个视囄的POSITION,完全
有可能既是pos==NULL又是pViewW合需要。当所需的视图是最后一个视图是最后一
个视囄时就如引。因此需采用两次判断?br />使用该函数应遵@如下格式Q以取得CTestView指针ZQ:
CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView));
RUNTIME_CLASS是一个宏Q可以简单地理解它的作用Q将cȝ名字转化?br />CRuntimeClass为指针。至于强制类型{换也是ؓ了安全特性考虑的,因ؓ从同一?br />基类之间的指针类型是互相兼容的。这U强制类型{换也许ƈ不必要,但能避免一
些可能出现的ȝ?br />
3.从一个视囄取得另一视图cȝ指针 l合1?Q很Ҏ得出视图cM间互相获?br />指针的方法:是用文档类作中转,先用1的方法得到文档类的指针,再用2的方法,
以文档类的视囑֮位函数取得另一个视囄。同P可以实现成一个函敎ͼ
Q假设要从CTestAView中取得指向其它视囄的指针)
CView* CTestAView::GetView(CRuntimeClass* pClass)
{
CTestDoc* pDoc=(CTestDoc*)GetDocument();
CView* pView;
POSITION pos=pDoc->GetFirstViewPosition();
while(pos!=NULL){
pView=pDoc->GetNextView(pos);
if(!pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass)){
AfxMessageBox("Connt Locate the View.");
return NULL;
}

return pView;
}
q个函数?中的GetView()相比Q一是多了第一句以取得文档cL针,二是?br />GetFirstViewPosition()和GetNextView()前加上了文档cL针,以表C它们是文档
cL员函数。有了此函数Q当要从CTestAView中取得CTestBView的指针时Q只需?br />下:CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));

11Q对于单文档中也可以加入多个文档模板Q但是一般的开发就使用MDI方式开?
多文档模板,其方法与上述视图的获取方法很接近Q这里稍做解释,如果不清楚,
h阅MSDNQ(以下四个内容Q?1?2?3?4Q来源:
http://sanjianxia.myrice.com/vc/vc45.htmQ?

可以用CWinApp::GetFirstDocTemplatePostion获得应用E序注册的第一个文档模?
的位|;利用该值来调用CWinApp::GetNextDocTemplate函数Q获得第一?
CDocTemplate对象指针?POSITION GetFirstDocTemplate( ) const; 
CDocTemplate *GetNextDocTemplate( POSITION & pos ) const;

W二个函数返回由pos 标识的文档模ѝPOSITION是MFC定义的一个用于P代或对象
指针索的倹{通过q两个函敎ͼ应用E序可以遍历整个文档模板列表。如果被?
的文档模板是模板列表中的最后一个,则pos参数被置为NULL?

 12Q一个文档模板可以有多个文档Q每个文档模杉K保留q维护了一个所有对应文
档的指针列表?
用CDocTemplate::GetFirstDocPosition函数获得与文档模板相关的文档集合中第一
个文档的位置Qƈ用POSITIONg为CDocTemplate::GetNextDoc的参数来重复遍历?
模板相关的文档列表。函数原形ؓQ?
viaual POSITION GetFirstDocPosition( ) const = 0; 
visual CDocument *GetNextDoc(POSITION & rPos) const = 0;  

如果列表为空Q则rPos被置为NULL. 

 13Q在文档中可以调用CDocument::GetDocTemplate获得指向该文档模板的指针?
函数原Ş如下Q?CDocTemplate * GetDocTemplate ( ) const; 
如果该文档不属于文档模板理Q则q回gؓNULL?

 14)一个文档可以有多个视。每一个文档都保留q维护一个所有相兌的列表?
CDocument::AddView一个视q接到文档上Q将该视加入到文档相联系的视的列?
中,q将视的文档指针指向该文档。当有File/New、File/Open、Windows/New?
Window/Split的命令而将一个新创徏的视的对象连接到文档上时Q?MFC会自动调?
该函敎ͼ框架通过文档/视的l构文档和视联pv来。当ӞE序员也可以Ҏ?
q需要调用该函数?
Virtual POSITION GetFirstViewPosition( ) const; 
Virtual CView * GetNextView( POSITION &rPosition) cosnt; 

应用E序可以调用CDocument::GetFirstViewPositionq回与调用文档相联系的视?
列表中的W一个视的位|,q调用CDocument::GetNextViewq回指定位置的视Qƈ?
rPositon的值置为列表中下一个视的POSITION倹{如果找到的视ؓ列表中的最后一?
视,则将rPosition|ؓNULL. 

 15)从一个视囄取得另一视图cȝ指针
q个应用在多视的应用E序中很多见Q一般如果自己在ȝ序或者主框架中做好变
量记P也可以获得,q有比较通用的就是用文档cM中{Q以文档cȝ视图遍历
定位Q取得另一个视囄。这个功能从本文W?0中可以得到?
讉K应用E序的其它类

获得CWinApp:
	-在CMainFrame,CChildFrame,CDocument,CView中直接调用AfxGetApp()或用theApp
	-在其它类中只能用AfxGetApp()

获得CMainFrame:
	-在CMinApp中用AfxGetMainWnd()或者m_pMainWnd
	-在CChildFrame中可用GetParentFrame()
	-在其它类中用AfxGetMainWnd()

获得CChildFrame:
	-在CView中用GetParentFrame()
	-在CMainFrame中用MDIGetActive()或GetActiveFrame()
	-在其它类中用AfxGetMainWnd()->MDIGetActive()或AfxGetMainWnd()->GetActiveFrame()

获得CDocument:
	-在CView中用GetDocument()
	-在CChildFrame中用GetActiveView()->GetDocument()
	-在CMainFrame中用
		-if SDI:GetActiveView()->GetDocument()
		-if MDI:MDIGetActive()->GetActiveView()->GetDocument()
	-在其它类?
		-if SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()
		-if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()

获得CView:
	-在CDocument?POSITION pos = GetFirstViewPosition();GetNextView(pos)
	-在CChildFrame?GetActiveView()
	-在CMainFrame?
		-if SDI:GetActiveView()
		-if MDI:MDIGetActive()->GetActiveView()
	-在其它类?
		-if SDI:AfxGetMainWnd()->GetActiveView()
		-if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()
讉K应用E序的其它类

获得CWinApp:
	-在CMainFrame,CChildFrame,CDocument,CView中直接调用AfxGetApp()或用theApp
	-在其它类中只能用AfxGetApp()

获得CMainFrame:
	-在CMinApp中用AfxGetMainWnd()或者m_pMainWnd
	-在CChildFrame中可用GetParentFrame()
	-在其它类中用AfxGetMainWnd()

获得CChildFrame:
	-在CView中用GetParentFrame()
	-在CMainFrame中用MDIGetActive()或GetActiveFrame()
	-在其它类中用AfxGetMainWnd()->MDIGetActive()或AfxGetMainWnd()->GetActiveFrame()

获得CDocument:
	-在CView中用GetDocument()
	-在CChildFrame中用GetActiveView()->GetDocument()
	-在CMainFrame中用
		-if SDI:GetActiveView()->GetDocument()
		-if MDI:MDIGetActive()->GetActiveView()->GetDocument()
	-在其它类?
		-if SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()
		-if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()

获得CView:
	-在CDocument?POSITION pos = GetFirstViewPosition();GetNextView(pos)
	-在CChildFrame?GetActiveView()
	-在CMainFrame?
		-if SDI:GetActiveView()
		-if MDI:MDIGetActive()->GetActiveView()
	-在其它类?
		-if SDI:AfxGetMainWnd()->GetActiveView()
		-if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()



David Lee 2008-09-19 01:13 发表评论
]]>
WTL的安装、用[转]http://www.shnenglu.com/Lee/archive/2008/09/18/62228.htmlDavid LeeDavid LeeThu, 18 Sep 2008 14:24:00 GMThttp://www.shnenglu.com/Lee/archive/2008/09/18/62228.htmlhttp://www.shnenglu.com/Lee/comments/62228.htmlhttp://www.shnenglu.com/Lee/archive/2008/09/18/62228.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/62228.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/62228.html 
WTL全称为Window Template Library,一个构架于ATL之上的C++cd,它包装了大多数的H口控制.从网上看?也只是个大概的了?先安装了弄个Hello World试试?呵呵
1,安装
   1.1 下个WTL安装?其实上个压羃?现在最新的?.0?默认解压目录为C:\WTL80,其中80为版本号,如果下的?.5则ؓC:\WTL75
   1.2 自动安装
   在目录C:\WTL80\AppWiz有四个JS文g,选择一个你机子上安装的VC版本,点击相应的JS脚本q行安装卛_,如VS2005的VC版本?.0,则相应文件ؓsetup80.js
   1.3 手动安装
   自动安装有时安装不成?如点L件后却打开了一个记事本,其实手动安装也挺不错?
   C:\WTL80\AppWiz\Files目录下的三个WTLAppWiz.*文g考到VC安装目录的vcprojects目录?如E:\Program Files\Microsoft Visual Studio 8\VC\vcprojects, 打开WTLAppWiz.vsz,原文件ؓ:


   VSWIZARD 7.0
   Wizard=VsWizard.VsWizardEngine

   Param="WIZARD_NAME = WTLAppWiz"
   Param="WIZARD_VERSION = 7.0"
   Param="ABSOLUTE_PATH = ."
   Param="FALLBACK_LCID = 1033"
   其改ؓ
   VSWIZARD 7.0
   Wizard=VsWizard.VsWizardEngine.8.0

   Param="WIZARD_NAME = WTLAppWiz"
   Param="WIZARD_VERSION = 7.0"
   Param="ABSOLUTE_PATH = C:\WTL80\AppWiz\Files"
   Param="FALLBACK_LCID = 1033"

   其中Wizard后面需加上WTL的版本号,否则能在VC里看到WTL目,但其向导无法工作

   Param ="ABSOLUTE_PATH后加上WTL解压的\?/p>

   新将目旉择WTL目,接默认选项生成目Q编译时会报'atlapp.h': No such file or directory错误。需要加一个编译\径,工具-->选项-->目和解x?->VC目录Q在左边选择包含文gQ把WTL解压目录下的C:\WTL80\include路径加上

   如果~译时报以下两个BugQ?/p>

   错误 1 fatal error CVT1100: 重复的资源。type:MANIFEST, name:1, language:0x0409 CVTRES
   错误 2 fatal error LNK1123: 转换?COFF 期间p|: 文g无效或损?sdf
    则说明资源文件有问题Q具体的原因未知Q从|上找我资料看,有以下四U解x法:

   1Q工E属?>配置属?> 清单工具->输入和输?>嵌入清单Q选择[否]

    2Q打开rc文gQ找MANIFESTQ所属段或行全去?/p>

   3Q打开此项目属性页Q链接器-->嵌入?IDL-->cd库资?ID 设一个从1-65535的?/p>

   4Q项目属性页链接?->清单 文g-->生成清单文g 选项讄为no



David Lee 2008-09-18 22:24 发表评论
]]>C++ 命名规则 (?http://www.shnenglu.com/Lee/archive/2008/09/16/62003.htmlDavid LeeDavid LeeTue, 16 Sep 2008 12:40:00 GMThttp://www.shnenglu.com/Lee/archive/2008/09/16/62003.htmlhttp://www.shnenglu.com/Lee/comments/62003.htmlhttp://www.shnenglu.com/Lee/archive/2008/09/16/62003.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/62003.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/62003.html    “匈牙利”法最大的~点是烦琐,例如

    int i, j, k;

    float x, y, z;

    倘若采用“匈牙利”命名规则,则应当写?/p>

    int iI, iJ, ik; // 前缀 i表示intcd

    float fX, fY, fZ; // 前缀 f表示floatcd

    如此烦琐的程序会让绝大多数程序员无法忍受?/p>

    据考察Q没有一U命名规则可以让所有的E序员赞同,E序设计教科书一般都不指定命名规则。命名规则对软g产品而言q不是“成败悠关”的事,我们不要化太多精力试囑֏明世界上最好的命名规则Q而应当制定一Uo大多数项目成员满意的命名规则Qƈ在项目中贯彻实施?/p>

    3.1 共性规?br />    本节的共性规则是被大多数E序员采U的Q我们应当在遵@q些共性规则的前提下,再扩充特定的规则Q如3.2节?/p>


    l 【规?-1-1】标识符应当直观且可以拼读,可望文知意,不必q行“解码”?/p>

    标识W最好采用英文单词或其组合,便于记忆和阅诅R切忌用汉语拼x命名。程序中的英文单词一般不会太复杂Q用词应当准。例如不要把CurrentValue写成NowValue?/p>


    l 【规?-1-2】标识符的长度应当符合“min-length && max-information”原则?/p>

    几十q前老ANSI C规定名字不准过6个字W,C?a class="channel_keylink" target="_blank">C++/C不再有此限制。一般来_长名字能更好地表辑֐义,所以函数名、变量名、类名长辑֍几个字符不为怪。那么名字是否越长约好?不见? 例如变量名maxval比maxValueUntilOverflow好用。单字符的名字也是有用的Q常见的如i,j,k,m,n,x,y,z{,它们通常可用作函数内的局部变量?/p>


    l 【规?-1-3】命名规则尽量与所采用的操作系l或开发工L风格保持一致?/p>

    例如Windows应用E序的标识符通常采用“大写”؜排的方式Q如AddChild。而Unix应用E序的标识符通常采用“小写加下划U쀝的方式Q如add_child。别把这两类风格混在一L?/p>


    l 【规?-1-4】程序中不要出现仅靠大小写区分的怼的标识符?/p>

    例如Q?/p>

    int x, X; // 变量x ?X Ҏh

    void foo(int x); // 函数foo 与FOOҎh

    void FOO(float x);


    l 【规?-1-5】程序中不要出现标识W完全相同的局部变量和全局变量Q尽两者的作用域不同而不会发生语法错误,但会使h误解?br />
  l 【规?-1-6】变量的名字应当使用“名词”或者“Ş容词Q名词”?

    例如Q?/p>

    float value;

    float oldValue;

    float newValue;


    l 【规?-1-7】全局函数的名字应当用“动词”或者“动词+名词”(动宾词组Q。类的成员函数应当只使用“动词”,被省略掉的名词就是对象本w?/p>

    例如Q?/p>

    DrawBox(); // 全局函数

    box->Draw(); // cȝ成员函数


    l 【规?-1-8】用正确的反义词l命名具有互斥意义的变量或相反动作的函数{?/p>

    例如Q?/p>

    int minValue;

    int maxValue;


    int SetValue(?;

    int GetValue(?;


    2 【徏?-1-1】尽量避免名字中出现数字~号Q如Value1,Value2{,除非逻辑上的需要编受这是ؓ了防止程序员hQ不肯ؓ命名动脑{而导致生无意义的名字(因ؓ用数字编h省事Q?/p>

    3.2 单的Windows应用E序命名规则
    作者对“匈牙利”命名规则做了合理的化,下述的命名规则简单易用,比较适合于Windows应用软g的开发?/p>


    l 【规?-2-1】类名和函数名用大写字母开头的单词l合而成?/p>

    例如Q?/p>

    class Node; // cd

    class LeafNode; // cd

    void Draw(void); // 函数



David Lee 2008-09-16 20:40 发表评论
]]>
指针Q?0Q指针的安全问题Q{Q?/title><link>http://www.shnenglu.com/Lee/archive/2008/09/16/61927.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Mon, 15 Sep 2008 18:02:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2008/09/16/61927.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/61927.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2008/09/16/61927.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/61927.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/61927.html</trackback:ping><description><![CDATA[看下面的例子Q?br />例十八:<br />char s='a';<br />int *ptr;<br />ptr=(int *)&s;<br />*ptr=1298Q?br />指针ptr 是一个int *cd的指针,它指向的cd是int。它指向<br />的地址是s 的首地址。在32 位程序中Qs 占一个字节,int cd占四<br />个字节。最后一条语句不但改变了s 所占的一个字节,q把和s 怏?br />高地址方向的三个字节也改变了。这三个字节是干什么的Q只有编译程<br />序知道,而写E序的h是不太可能知道的。也许这三个字节里存储了?br />帔R要的数据Q也许这三个字节里正好是E序的一条代码,而由于你?br />指针的马虎应用,q三个字节的D改变了!q会造成崩溃性的错误?br />让我们再来看一例:<br />例十九:<br />char a;<br />int *ptr=&a;<br />ptr++;<br />*ptr=115;<br />该例子完全可以通过~译Qƈ能执行。但是看到没有?W? 句对?br />针ptr q行自加1 q算后,ptr 指向了和整Ş变量a 盔R的高地址方向<br />的一块存储区。这块存储区里是什么?我们不知道。有可能它是一个非<br />帔R要的数据Q甚臛_能是一条代码。而第4 句竟然往q片存储区里?br />入一个数据!q是严重的错误。所以在使用指针ӞE序员心里必非<br />常清楚:我的指针I竟指向了哪里。在用指针访问数l的时候,也要?br />意不要超出数l的低端和高端界限,否则也会造成cM的错误?br />在指针的强制cd转换Qptr1=(TYPE *)ptr2 中,如果sizeof(ptr2<br />的类?大于sizeof(ptr1 的类?Q那么在使用指针ptr1 来访问ptr2<br />所指向的存储区时是安全的。如果sizeof(ptr2 的类? 于<br />sizeof(ptr1 的类?Q那么在使用指针ptr1 来访问ptr2 所指向的存<br />储区时是不安全的。至于ؓ什么,读者结合例十八来想一惻I应该会明<br />白的?img src ="http://www.shnenglu.com/Lee/aggbug/61927.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2008-09-16 02:02 <a href="http://www.shnenglu.com/Lee/archive/2008/09/16/61927.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>指针Q?Q指针类型{换(转)http://www.shnenglu.com/Lee/archive/2008/09/15/61887.htmlDavid LeeDavid LeeMon, 15 Sep 2008 13:32:00 GMThttp://www.shnenglu.com/Lee/archive/2008/09/15/61887.htmlhttp://www.shnenglu.com/Lee/comments/61887.htmlhttp://www.shnenglu.com/Lee/archive/2008/09/15/61887.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/61887.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/61887.html针,赋值号的右Ҏ一个指针表辑ּ。在我们前面所丄例子中,l大
多数情况下,指针的类型和指针表达式的cd是一LQ指针所指向?br />cd和指针表辑ּ所指向的类型是一L?br />例十五:
float f=12.3;
float *fptr=&f;
int *p;
在上面的例子中,假如我们惌指针p 指向实数fQ应该怎么办?
是用下面的语句吗Q?br />p=&f;
不对。因为指针p 的类型是int *Q它指向的类型是int。表辑ּ
&f 的结果是一个指针,指针的类型是float *,它指向的cd是float?br />两者不一_直接赋值的Ҏ是不行的。至在我的MSVC++6.0 上,?br />指针的赋D句要求赋值号两边的类型一_所指向的类型也一_?br />它的~译器上我没试过Q大家可以试试。ؓ了实现我们的目的Q需要进
?强制cd转换"Q?br />p=(int*)&f;
如果有一个指针pQ我们需要把它的cd和所指向的类型改?br />TYEP *TYPEQ?那么语法格式是: (TYPE *)pQ?br />q样强制cd转换的结果是一个新指针Q该新指针的cd?br />TYPE *Q它指向的类型是TYPEQ它指向的地址是原指针指向的地址?br />而原来的指针p 的一切属性都没有被修攏V(切记Q?br />一个函数如果用了指针作ؓ形参Q那么在函数调用语句的实参和
形参的结合过E中Q必M证类型一_否则需要强制{?br />例十六:
void fun(char*);
int a=125,b;
fun((char*)&a);
void fun(char*s)
{
charc;
c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;
c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;
}
注意q是一?2 位程序,故int cd占了四个字节Qchar cd占一?br />字节。函数fun 的作用是把一个整数的四个字节的顺序来个颠倒。注?br />C吗?在函数调用语句中Q实?amp;a 的结果是一个指针,它的cd?br />int *Q它指向的类型是int。Ş参这个指针的cd是char *Q它指向
的类型是char。这P在实参和形参的结合过E中Q我们必进行一
ơ从int *cd到char *cd的{换。结合这个例子,我们可以q样?br />惌~译器进行{换的q程Q编译器先构造一个时指针char *tempQ?br />然后执行temp=(char *)&aQ最后再把temp 的g递给s。所以最后的
l果是:s 的类型是char *,它指向的cd是charQ它指向的地址是
a 的首地址?br />我们已经知道Q指针的值就是指针指向的地址Q在32 位程序中Q?br />指针的值其实是一?2 位整数。那可不可以把一个整数当作指针的?br />直接赋给指针呢?p下面的语句:
unsigned int a;
TYPE *ptr; //TYPE 是intQchar 或结构类型等{类型?br />a=20345686;
ptr=20345686; //我们的目的是要指针ptr 指向地址20345686
ptr=a; //我们的目的是要指针ptr 指向地址20345686
~译一下吧。结果发现后面两条语句全是错的。那么我们的目的׃?br />辑ֈ了吗Q不Q还有办法:
unsigned int a;
TYPE *ptr; //TYPE 是intQchar 或结构类型等{类型?br />a=N //N 必须代表一个合法的地址Q?br />ptr=(TYPE*)aQ?//呵呵Q这可以了?br />严格说来q里?TYPE *)和指针类型{换中?TYPE *)q不一栗这?br />?TYPE*)的意思是把无W号整数a 的值当作一个地址来看待。上面强
调了a 的值必M表一个合法的地址Q否则的话,在你使用ptr 的时候,
׃出现非法操作错误?br />x能不能反q来Q把指针指向的地址x针的值当作一个整数取
出来。完全可以。下面的例子演示了把一个指针的值当作一个整数取?br />来,然后再把q个整数当作一个地址赋给一个指针:
例十七:
int a=123,b;
int *ptr=&a;
char *str;
b=(int)ptr; //把指针ptr 的值当作一个整数取出来?br />str=(char*)b; //把这个整数的值当作一个地址赋给指针str?br />现在我们已经知道了,可以把指针的值当作一个整数取出来Q也?br />以把一个整数值当作地址赋给一个指针?img src ="http://www.shnenglu.com/Lee/aggbug/61887.html" width = "1" height = "1" />

David Lee 2008-09-15 21:32 发表评论
]]>
指针Q?Q?指针和函数的关系Q{Q?/title><link>http://www.shnenglu.com/Lee/archive/2008/09/11/61572.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Thu, 11 Sep 2008 04:02:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2008/09/11/61572.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/61572.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2008/09/11/61572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/61572.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/61572.html</trackback:ping><description><![CDATA[可以把一个指针声明成Z个指向函数的指针?br />int fun1(char *,int);<br />int (*pfun1)(char *,int);<br />pfun1=fun1;<br />int a=(*pfun1)("abcdefg",7); //通过函数指针调用函数?br />可以把指针作为函数的形参。在函数调用语句中,可以用指针表辑ּ?br />作ؓ实参?br />例十四:<br />int fun(char *);<br />inta;<br />char str[]="abcdefghijklmn";<br />a=fun(str);<br />int fun(char *s)<br />{<br />int num=0;<br />for(int i=0;;)<br />{<br />num+=*s;s++;<br />}<br />return num;<br />}<br /><br />q个例子中的函数fun l计一个字W串中各个字W的ASCII 码g<br />和。前面说了,数组的名字也是一个指针。在函数调用中,当把str<br />作ؓ实参传递给形参s 后,实际是把str 的g递给了sQs 所指向?br />地址和str 所指向的地址一_但是str 和s 各自占用各自的存储空<br />间。在函数体内对s q行自加1 q算Qƈ不意味着同时对str q行了自<br />? q算?img src ="http://www.shnenglu.com/Lee/aggbug/61572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2008-09-11 12:02 <a href="http://www.shnenglu.com/Lee/archive/2008/09/11/61572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>指针Q?Q?指针和结构类型的关系Q{Q?/title><link>http://www.shnenglu.com/Lee/archive/2008/09/11/61566.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Thu, 11 Sep 2008 02:33:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2008/09/11/61566.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/61566.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2008/09/11/61566.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/61566.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/61566.html</trackback:ping><description><![CDATA[可以声明一个指向结构类型对象的指针?br />例十二:<br />struct MyStruct<br />{<br />int a;<br />int b;<br />int c;<br />};<br />struct MyStruct ss={20,30,40};<br />//声明了结构对象ssQƈ把ss 的成员初始化?0Q?0 ?0?br />struct MyStruct *ptr=&ss;<br />//声明了一个指向结构对象ss 的指针。它的类型是<br />//MyStruct *,它指向的cd是MyStruct?br />int *pstr=(int*)&ss;<br />//声明了一个指向结构对象ss 的指针。但是pstr ?br />//它被指向的类型ptr 是不同的?br />请问怎样通过指针ptr 来访问ss 的三个成员变量?<br />{案Q?br />ptr->a; //指向q算W,或者可以这?*ptr).a,使用前?br />ptr->b;<br />ptr->c;<br />又请问怎样通过指针pstr 来访问ss 的三个成员变量?<br />{案Q?br />*pstrQ?//讉K了ss 的成员a?br />*(pstr+1); //讉K了ss 的成员b?br />*(pstr+2) //讉K了ss 的成员c?br />虽然我在我的MSVC++6.0 上调式过上述代码Q但是要知道Q这样<br />用pstr 来访问结构成员是不正规的Qؓ了说明ؓ什么不正规Q让我们<br />看看怎样通过指针来访问数l的各个单元: (结构体换成数组)<br />例十三:<br />int array[3]={35,56,37};<br />int *pa=array;<br />通过指针pa 讉K数组array 的三个单元的Ҏ是:<br />*pa; //讉K了第0 号单?br />*(pa+1); //讉K了第1 号单?br />*(pa+2); //讉K了第2 号单?br />从格式上看倒是与通过指针讉Kl构成员的不正规Ҏ的格式一<br />栗?br />所有的C/C++~译器在排列数组的单元时QL把各个数l单元存<br />攑֜q箋的存储区里,单元和单元之间没有空隙。但在存攄构对象的<br />各个成员Ӟ在某U编译环境下Q可能会需要字寚w或双字对齐或者是<br />别的什么对齐,需要在盔R两个成员之间加若q个"填充字节"Q这导<br />致各个成员之间可能会有若q个字节的空隙?br />所以,在例十二中,即*pstr 讉KCl构对象ss 的第一个成<br />员变量aQ也不能保证*(pstr+1)׃定能讉K到结构成员b。因为成?br />a 和成员b 之间可能会有若干填充字节Q说不定*(pstr+1)正好访?br />Cq些填充字节呢。这也证明了指针的灵zL。要是你的目的就是想<br />看看各个l构成员之间到底有没有填充字节,嘿,q倒是个不错的Ҏ?br />不过指针讉Kl构成员的正方法应该是象例十二中用指针ptr ?br />Ҏ?img src ="http://www.shnenglu.com/Lee/aggbug/61566.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2008-09-11 10:33 <a href="http://www.shnenglu.com/Lee/archive/2008/09/11/61566.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(?指针(6) 数组和指针的关系http://www.shnenglu.com/Lee/archive/2008/09/09/61433.htmlDavid LeeDavid LeeTue, 09 Sep 2008 15:48:00 GMThttp://www.shnenglu.com/Lee/archive/2008/09/09/61433.htmlhttp://www.shnenglu.com/Lee/comments/61433.htmlhttp://www.shnenglu.com/Lee/archive/2008/09/09/61433.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/61433.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/61433.html例九Q?br />intarray[10]={0,1,2,3,4,5,6,7,8,9},value;
value=array[0]; //也可写成Qvalue=*array;
value=array[3]; //也可写成Qvalue=*(array+3);
value=array[4]; //也可写成Qvalue=*(array+4);
上例中,一般而言数组名array 代表数组本nQ类型是int[10]Q但?br />果把array 看做指针的话Q它指向数组的第0 个单元,cd是int* Q?br />所指向的类型是数组单元的类型即int。因?array {于0 ׃点也?br />奇怪了。同理,array+3 是一个指向数l第3 个单元的指针Q所?br />*(array+3){于3。其它依此类推?br />例十Q?br />char *str[3]={
"Hello,thisisasample!",
"Hi,goodmorning.",
"Helloworld"
};
chars[80]Q?br />strcpy(s,str[0]); //也可写成strcpy(s,*str);
strcpy(s,str[1]); //也可写成strcpy(s,*(str+1));
strcpy(s,str[2]); //也可写成strcpy(s,*(str+2));
上例中,str 是一个三单元的数l,该数l的每个单元都是一个指针,
q些指针各指向一个字W串。把指针数组名str 当作一个指针的话,?br />指向数组的第0 号单元,它的cd是char **Q它指向的类型是char *?br />*str 也是一个指针,它的cd是char *Q它所指向的类型是charQ它
指向的地址是字W串"Hello,thisisasample!"的第一个字W的地址Q即
'H'的地址。注?字符串相当于是一个数l?在内存中以数l的形式?br />?只不q字W串是一个数l常?内容不可改变,且只能是叛_?如果
看成指针的话,他即是常量指?也是指针帔R.
str+1 也是一个指针,它指向数l的W? 号单元,它的cd是char**Q?br />它指向的cd是char*?br />*(str+1)也是一个指针,它的cd是char*Q它所指向的类型是charQ?br />它指?Hi,goodmorning."的第一个字W?H'
下面ȝ一下数l的数组?数组中储存的也是数组)的问?
声明了一个数lTYPE array[n]Q则数组名称array 有了两重含义:
W一Q它代表整个数组Q它的类型是TYPE[n]Q第二,它是一个常?br />指针Q该指针的类型是TYPE*Q该指针指向的类型是TYPEQ也是数组
单元的类型,该指针指向的内存区就是数l第0 号单元,该指针自己占
有单独的内存区,注意它和数组W? 号单元占据的内存区是不同的。该
指针的值是不能修改的,即类似array++的表辑ּ是错误的?br />在不同的表达式中数组名array 可以扮演不同的角艌Ӏ?br />在表辑ּsizeof(array)中,数组名array 代表数组本nQ故q时
sizeof 函数出的是整个数组的大?br />在表辑ּ*array 中,array 扮演的是指针Q因此这个表辑ּ的结果就?br />数组W? 号单元的倹{sizeof(*array)出的是数组单元的大?br />表达式array+nQ其中n=0Q?Q?Q?....Q中Qarray 扮演的是?br />针,故array+n 的结果是一个指针,它的cd是TYPE *Q它指向的类
型是TYPEQ它指向数组Wn 号单元。故sizeof(array+n)出的是指针
cd的大。在32 位程序中l果?
例十一:
int array[10];
int (*ptr)[10];
ptr=&array;Q?br />上例中ptr 是一个指针,它的cd是int(*)[10]Q他指向的类型是
int[10] Q我们用整个数组的首地址来初始化它。在语句ptr=&array
中,array 代表数组本n?br />本节中提C函数sizeof()Q那么我来问一问,sizeof(指针名称)
出的究竟是指针自ncd的大呢q是指针所指向的类型的大小Q?br />{案是前者。例如:
int(*ptr)[10];
则在32 位程序中Q有Q?br />sizeof(int(*)[10])==4
sizeof(int[10])==40
sizeof(ptr)==4
实际上,sizeof(对象)出的都是对象自w的cd的大,而不是别?br />什么类型的大小?img src ="http://www.shnenglu.com/Lee/aggbug/61433.html" width = "1" height = "1" />

David Lee 2008-09-09 23:48 发表评论
]]>
引用的作?Q{Q?/title><link>http://www.shnenglu.com/Lee/archive/2008/09/06/61093.html</link><dc:creator>David Lee</dc:creator><author>David Lee</author><pubDate>Sat, 06 Sep 2008 01:51:00 GMT</pubDate><guid>http://www.shnenglu.com/Lee/archive/2008/09/06/61093.html</guid><wfw:comment>http://www.shnenglu.com/Lee/comments/61093.html</wfw:comment><comments>http://www.shnenglu.com/Lee/archive/2008/09/06/61093.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Lee/comments/commentRss/61093.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Lee/services/trackbacks/61093.html</trackback:ping><description><![CDATA[ <div class="6611611" id="BlogArticleDetail" style="FONT-SIZE: 14px">分析以下E序的执行结?<br />#include<iostream.h> <br />class Sample <br />{ <br />int x,y; <br />public: <br />Sample(){x=y=0;} <br />Sample(int i,int j){x=i;y=j;} <br />void copy(Sample &s); <br />void setxy(int i,int j){x=i;y=j;} <br />void print(){cout<<"x="<<x<<",y="<<y<<endl;} <br />}; <br />void Sample::copy(Sample &s) <br />{ <br />x=s.x;y=s.y; <br />} <br />void func(Sample s1,Sample &s2) <br />{ <br />s1.setxy(10,20); <br />s2.setxy(30,40); <br />} <br />void main() <br />{ <br />Sample p(1,2),q; <br />q.copy(p); <br />func(p,q); <br />p.print(); <br />q.print(); <br />} <br />解: <br />本题说明对象引用作ؓ函数参数的作用。SamplecM的copy()成员函数q行对象拯。在main()中先建立对象p和qQp与q对象的x,y值相?调用func()函数Q由于第2个参Cؓ引用cdQ故实参发生改变Q而第1个参C是引用类型,实参不发生改变。所以输ZؓQ?<br />x=1,y=2 <br />x=30,y=40 <br /><br />===============================================================================================<br /><br />众所周知Q引用作为函数参数可以避免参数对象的额外拯Q对于非内置cdQ一般而言可以获得更高的效率,同时比指针更安全Q语义也更清晰?br />   但是除此之外引用有什么特别的作用呢?<br />   在同一个作用域的引用,像q样Q?br />   void f()<br />   {<br />   int i = 0;<br />   int &ri = i; //q里?br />   //...<br />   }<br />   <br />   事实上,在f的内部,需要操作i的地方,完全可以直接使用iQ而不必要使用ri间接操作Q用i在语义上更明。而؜合用i和ri反倒容易引起逻辑的؜乱?br />   gq是一个鸡肋,但是其实不是? <p>   q里引用乑֝一W文章中的例子:<br />                例一、用C宏,书写代码更简z?br />                q段代码写网l程序的朋友都很眼熟Q是Net/3中mbuf的实现?br />                <br />                struct mbuf<br />                {<br />                    struct m_hdr mhdr;<br />                    union {<br />                        struct <br />                        {<br />                            struct pkthdr MH_pkthdr; /* M_PKTHDR set */<br />                            union <br />                            {<br />                                struct m_ext MH_ext; /* M_EXT set */<br />                                char MH_databuf[MHLEN];<br />                            } MH_dat;<br />                        } MH;<br />                        char M_databuf[MLEN];        /* !M_PKTHER, !M_EXT*/<br />                    } M_dat;<br />                };<br />                <br />                上面的代码,假如我想讉K最里层的MH_databufQ那么我必须写M_dat.MH.MH_dat.MH_databuf; q是不是很长Q很隑ֆ呀Q这L代码阅读h也不明了。其实,对于MH_pkthdr、MH_ext、MH_databuf来说Q虽然不是在一个结构层ơ上Q但是如果我们站在mbuf之外来看Q它们都是mbuf的属性,完全可以压扁C个^面上ȝ。所以,源码中有q么一l宏Q?br />                <br />                #define m_next      m_hdr.mh_next<br />                #define m_len       m_hdr.mh_len<br />                #define m_data      m_hdr.mh_data<br />                ... ...<br />                #define m_pkthdr    M_dat.MH.MH_pkthdr<br />                #define m_pktdat    M_dat.MH.MH_dat.MH_databuf<br />                ... ...<br />                <br />                q样写v代码来,是不是很_呢!</p><p>    q里用宏很y妙的解决了访问深层数据的问题Q但是宏的固有缺点也被引入了代码中,同时Q如果其他地Ҏ意中引用了这个宏定义的头文gQ而且恰好使用了名为m_pktdat的数据成员,那这个宏带来的后果可׃是我们想要的了?br />    事实上用引用也可以达到类似的效果Q不q必L在用的时候。由于引用不是标准C的组成部分,所以这只是一个C++技巧?br />    //假如代码是这LQ?br />    mbuf m; //q里的mbuf是前面的struct mbuf?br />            //如果要用MH_ext成员Q可以这P<br />    m_ext &MH_ext = m.M_dat.MH.MH_dat.MH_ext;<br />    //然后你的代码中就可以直接使用MH_ext作ؓm.M_dat.MH.MH_dat.MH_ext的替代品了?br />    也许看v来不是很自然Q不q这无疑是一U很直接的方法。你q可以通过一个const引用来在逻辑上避免无意的写操作?br />    实际的“面向对象”的C++代码中,不推荐直接数据成员的讉KQ取而代之的是用Get()和Set()Ҏ存取数据Q有些h只用GetQ通过q回一个成员的引用来达到读写数据成员的双重目的Q这时候,你可以在外部定义一个引用接受函数的q回Q从而避免每ơ都要写(XXX.Get()).Get()q种拖沓的语句来讉K一个深层的成员?br />    <br />    引用的另一个作用,是“别名”。别名是引用的另一U翻译,很明的表达了引用的另一个作用?br />    仅仅是ؓ了代码的可读性:<br />    //下面的代?br />    int i = 0,j = 0;<br />    //...<br />    for( i = 0; i < 10; i++)<br />        for( j = 0; j < 10; j++ )<br />            a[i][j] = 0;<br />    //你能明白q段代码的含义嘛Q有点困难,i和j的含义是不明的Q无法一眼看透?br />    假如Ҏq样Q?br />    const int width = 10;<br />    const int height = 10;<br />    //...<br />    int i = 0,j = 0;<br />    //...<br />    int &line = i;<br />    int &row = j;<br />    for(line = 0;line < height;line++)<br />        for(row = 0;row < width;row++)<br />            a[line][row] = 0;<br />    //是不是好了一点?<br />    //qƈ不是一个典型的例子Q因为i和j的定义是L的,某些情况你必M用别人给定的名称很郁L变量Q而他们又必须用来表达截然不同的含义,q时候一个引用往往可以让你清爽很多?br />    <br />    再看下面q个例子Q?br />    class CA<br />        {<br />                int m_i;<br />        public:<br />                int &i;<br />                int const &c_i;<br />                CA():i(m_i),c_i(m_i){};<br />        };<br />    q是一个简单的c,与所谓的“面向对象”的Ҏ不同Q这里用引用实现内部数据的公用接口。这个手法用来对?乑֝一W?的另一D话Q?br />         q就是偶说的PME模型的问题了Qdelphi、java、c#之类的语a都提供一U叫做属性的语法Q大概是q个样子的:</p><p>                class A<br />                {<br />                property int x<br />                {<br />                get {return x;}<br />                set {x = value;}<br />                }<br />                };<br />                <br />                A a;<br />                q样, 可以这么访问了 a.x = 8; int b = a.x;<br />                <br />                q比?a.setx(8); b=a.getx()Q直观多了?/p><p>    你可以用 CA a; a.i讉KCA的私有数据成员,辑ֈ像属性方法那L效果。但是这个方法在VC6下的表现却不如人意Q因为它存储了一个指针用来取代语法上的引用,q导致类体积不必要的扩张Q是我们所不希望看到的。也许在实现上确实存在难度,不过q是希望有更好的~译器能实现真正意义的引用接口?br />    q个例子其实是上面深层数据成员访问的一个引生?br />    引用Q作为C++的一个特D手法,也许q有很多不ؓ人知的作用等待我们去发掘呢~<br />    <br />    注:文中的代码ƈ未经q严格测试,有兴的读者可以自己测试代码的有效性?br />    本文引用的?乑֝一W?的内容均Q?br />    <a >http://blog.vckbase.com/smileonce/archive/2005/03/27/4081.html</a></p></div> <img src ="http://www.shnenglu.com/Lee/aggbug/61093.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Lee/" target="_blank">David Lee</a> 2008-09-06 09:51 <a href="http://www.shnenglu.com/Lee/archive/2008/09/06/61093.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ q算W优先列表 http://www.shnenglu.com/Lee/archive/2008/09/04/60962.htmlDavid LeeDavid LeeThu, 04 Sep 2008 14:15:00 GMThttp://www.shnenglu.com/Lee/archive/2008/09/04/60962.htmlhttp://www.shnenglu.com/Lee/comments/60962.htmlhttp://www.shnenglu.com/Lee/archive/2008/09/04/60962.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/60962.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/60962.html Precedence Operator Description Example Associativity 1 ()
[]
->
.
::
++
-- Grouping operator
Array access
Member access from a pointer
Member access from an object
Scoping operator
Post-increment
Post-decrement (a + b) / 4;
array[4] = 2;
ptr->age = 34;
obj.age = 34;
Class::age = 2;
for( i = 0; i < 10; i++ ) ...
for( i = 10; i > 0; i-- ) ... left to right 2 !
~
++
--
-
+
*
&
(type)
sizeof Logical negation
Bitwise complement
Pre-increment
Pre-decrement
Unary minus
Unary plus
Dereference
Address of
Cast to a given type
Return size in bytes if( !done ) ...
flags = ~flags;
for( i = 0; i < 10; ++i ) ...
for( i = 10; i > 0; --i ) ...
int i = -1;
int i = +1;
data = *ptr;
address = &obj;
int i = (int) floatNum;
int size = sizeof(floatNum); right to left 3 ->*
.* Member pointer selector
Member pointer selector ptr->*var = 24;
obj.*var = 24; left to right 4 *
/
% Multiplication
Division
Modulus int i = 2 * 4;
float f = 10 / 3;
int rem = 4 % 3; left to right 5 +
- Addition
Subtraction int i = 2 + 3;
int i = 5 - 1; left to right 6 <<
>> Bitwise shift left
Bitwise shift right int flags = 33 << 1;
int flags = 33 >> 1; left to right 7 <
<=
>
>= Comparison less-than
Comparison less-than-or-equal-to
Comparison greater-than
Comparison geater-than-or-equal-to if( i < 42 ) ...
if( i <= 42 ) ...
if( i > 42 ) ...
if( i >= 42 ) ... left to right 8 ==
!= Comparison equal-to
Comparison not-equal-to if( i == 42 ) ...
if( i != 42 ) ... left to right 9 & Bitwise AND flags = flags & 42; left to right 10 ^ Bitwise exclusive OR flags = flags ^ 42; left to right 11 | Bitwise inclusive (normal) OR flags = flags | 42; left to right 12 && Logical AND if( conditionA && conditionB ) ... left to right 13 || Logical OR if( conditionA || conditionB ) ... left to right 14 ? : Ternary conditional (if-then-else) int i = (a > b) ? a : b; right to left 15 =
+=
-=
*=
/=
%=
&=
^=
|=
<<=
>>= Assignment operator
Increment and assign
Decrement and assign
Multiply and assign
Divide and assign
Modulo and assign
Bitwise AND and assign
Bitwise exclusive OR and assign
Bitwise inclusive (normal) OR and assign
Bitwise shift left and assign
Bitwise shift right and assign int a = b;
a += 3;
b -= 4;
a *= 5;
a /= 2;
a %= 3;
flags &= new_flags;
flags ^= new_flags;
flags |= new_flags;
flags <<= 2;
flags >>= 2; right to left 16 , Sequential evaluation operator for( i = 0, j = 0; i < 10; i++, j++ ) ... left to right http://www.cppreference.com/operator_precedence.html

David Lee 2008-09-04 22:15 发表评论
]]>
(?指针Q?Q指针表辑ּhttp://www.shnenglu.com/Lee/archive/2008/09/04/60895.htmlDavid LeeDavid LeeThu, 04 Sep 2008 05:03:00 GMThttp://www.shnenglu.com/Lee/archive/2008/09/04/60895.htmlhttp://www.shnenglu.com/Lee/comments/60895.htmlhttp://www.shnenglu.com/Lee/archive/2008/09/04/60895.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/60895.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/60895.html一个表辑ּ的结果如果是一个指针,那么q个表达式就叫指针表式?br />下面是一些指针表辑ּ的例子:
例七Q?br />int a,b;
int array[10];
int *pa;
pa=&a; //&a 是一个指针表辑ּ?br />Int **ptr=&pa; //&pa 也是一个指针表辑ּ?br />*ptr=&b; //*ptr ?amp;b 都是指针表达式?br />pa=array;
pa++; //q也是指针表辑ּ?br />例八Q?br />char *arr[20];
char **parr=arr; //如果把arr 看作指针的话Qarr 也是指针表达?br />char *str;
str=*parr; //*parr 是指针表辑ּ
str=*(parr+1); //*(parr+1)是指针表辑ּ
str=*(parr+2); //*(parr+2)是指针表辑ּ
׃指针表达式的l果是一个指针,所以指针表辑ּ也具有指针所
h的四个要素:指针的类型,指针所指向的类型,指针指向的内存区Q?br />指针自n占据的内存?br />好了Q当一个指针表辑ּ的结果指针已l明地h了指针自w占
据的内存的话Q这个指针表辑ּ是一个左|否则׃是一个左倹{?br />在例七中Q?amp;a 不是一个左|因ؓ它还没有占据明确的内存?ptr ?br />一个左|因ؓ*ptr q个指针已经占据了内存,其实*ptr 是指针paQ?br />既然pa 已经在内存中有了自己的位|,那么*ptr 当然也有了自q?br />|?img src ="http://www.shnenglu.com/Lee/aggbug/60895.html" width = "1" height = "1" />

David Lee 2008-09-04 13:03 发表评论
]]>
Q{Q? 指针Q?Q?q算W?amp;?http://www.shnenglu.com/Lee/archive/2008/08/31/60547.htmlDavid LeeDavid LeeSun, 31 Aug 2008 14:42:00 GMThttp://www.shnenglu.com/Lee/archive/2008/08/31/60547.htmlhttp://www.shnenglu.com/Lee/comments/60547.htmlhttp://www.shnenglu.com/Lee/archive/2008/08/31/60547.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/60547.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/60547.html&a 的运结果是一个指针,指针的类型是a 的类型加?Q指针所
指向的类型是a 的类型,指针所指向的地址嘛,那就是a 的地址?br />*p 的运结果就五花八门了。M*p 的结果是p 所指向的东西,
q个东西有这些特点:它的cd是p 指向的类型,它所占用的地址是p
所指向的地址?br />例六Q?br />int a=12; int b; int *p; int **ptr;
p=&a; //&a 的结果是一个指针,cd是int*Q指向的cd?br />//intQ指向的地址是a 的地址?br />*p=24; //*p 的结果,在这里它的类型是intQ它所占用的地址?br />//p 所指向的地址Q显Ӟ*p 是变量a?br />ptr=&p; //&p 的结果是个指针,该指针的cd是p 的类型加?Q?br />//在这里是int **。该指针所指向的类型是p 的类型,q?br />//里是int*。该指针所指向的地址是指针p 自己的地址?br />*ptr=&b; //*ptr 是个指针Q?amp;b 的结果也是个指针Q且q两个指?br />//的类型和所指向的类型是一LQ所以用&b 来给*ptr ?br />//值就是毫无问题的了?br />**ptr=34; //*ptr 的结果是ptr 所指向的东西,在这里是一个指针,
//对这个指针再做一?q算Q结果是一个int cd的变量?img src ="http://www.shnenglu.com/Lee/aggbug/60547.html" width = "1" height = "1" />

David Lee 2008-08-31 22:42 发表评论
]]>
Q{Q?指针Q?Q指针的术q算http://www.shnenglu.com/Lee/archive/2008/08/31/60544.htmlDavid LeeDavid LeeSun, 31 Aug 2008 14:19:00 GMThttp://www.shnenglu.com/Lee/archive/2008/08/31/60544.htmlhttp://www.shnenglu.com/Lee/comments/60544.htmlhttp://www.shnenglu.com/Lee/archive/2008/08/31/60544.html#Feedback0http://www.shnenglu.com/Lee/comments/commentRss/60544.htmlhttp://www.shnenglu.com/Lee/services/trackbacks/60544.htmlq算的意义是不一LQ以单元为单位。例如:
例二Q?br />char a[20];
int *ptr=(int *)a; //强制cd转换q不会改变a 的类?br />ptr++;
在上例中Q指针ptr 的类型是int*,它指向的cd是intQ它被初始化
为指向整型变量a。接下来的第3 句中Q指针ptr 被加?Q编译器是这?br />处理的:它把指针ptr 的值加上了sizeof(int)Q在32 位程序中Q是被加?br />?Q因为在32 位程序中Qint ? 个字节。由于地址是用字节做单位的Q?br />故ptr 所指向的地址由原来的变量a 的地址向高地址方向增加? 个字节?br />׃char cd的长度是一个字节,所以,原来ptr 是指向数la 的第0 ?br />单元开始的四个字节Q此时指向了数组a 中从W? 号单元开始的四个字节?br />我们可以用一个指针和一个@环来遍历一个数l,看例子:
例三Q?br />int array[20]={0};
int *ptr=array;
for(i=0;i<20;i++)
{
(*ptr)++;
ptr++Q?br />}
q个例子整型数l中各个单元的值加1。由于每ơ@环都指针ptr
? 个单元,所以每ơ@环都能访问数l的下一个单元?br />再看例子Q?br />例四Q?br />char a[20]="You_are_a_girl";
int *ptr=(int *)a;
ptr+=5;
在这个例子中Qptr 被加上了5Q编译器是这样处理的Q将指针ptr ?br />值加? 乘sizeof(int)Q在32 位程序中是加上? ?=20。由于地址
的单位是字节Q故现在的ptr 所指向的地址比v? 后的ptr 所指向的地址
来说Q向高地址方向Ud?0 个字节。在q个例子中,没加5 前的ptr ?br />向数la 的第0 号单元开始的四个字节Q加5 后,ptr 已经指向了数la ?br />合法范围之外了。虽然这U情况在应用上会出问题,但在语法上却是可以的?br />q也体现Z指针的灵zL?br />如果上例中,ptr 是被减去5Q那么处理过E大同小异,只不qptr ?br />值是被减? 乘sizeof(int)Q新的ptr 指向的地址比原来的ptr 所指向
的地址向低地址方向Ud?0 个字节?br />下面请允许我再D一个例?(一个误?
例五:
#include<stdio.h>
int main()
{
char a[20]=" You_are_a_girl";
char *p=a;
char **ptr=&p;
//printf("p=%d\n",p);
//printf("ptr=%d\n",ptr);
//printf("*ptr=%d\n",*ptr);
printf("**ptr=%c\n",**ptr);
ptr++;
//printf("ptr=%d\n",ptr);
//printf("*ptr=%d\n",*ptr);
printf("**ptr=%c\n",**ptr);
}
误区一、输出答案ؓY 和o
误解:ptr 是一个char 的二U指?当执行ptr++;?会指针加一?br />sizeof(char),所以输出如上结?q个可能只是部分h的结?
误区二、输出答案ؓY 和a
误解:ptr 指向的是一个char *cd,当执行ptr++;?会指针加一?br />sizeof(char *)(有可能会有h认ؓq个gؓ1,那就会得到误Z的答
?q个值应该是4,参考前面内?, ?amp;p+4; 那进行一ơ取D不
指向数l中的第五个元素了吗?那输出的l果不就是数l中W五个元
素了?{案是否定的.
正解: ptr 的类型是char **,指向的类型是一个char *cd,该指向的
地址是p的地址(&p),当执行ptr++;?会指针加一个sizeof(char
*),?amp;p+4;?(&p+4)指向哪呢,q个你去问上帝吧,或者他会告诉你?br />?所以最后的输出会是一个随机的?或许是一个非法操?
ȝ一?
一个指针ptrold ??一个整数n 后,l果是一个新的指针ptrnewQ?br />ptrnew 的类型和ptrold 的类型相同,ptrnew 所指向的类型和ptrold
所指向的类型也相同。ptrnew 的值将比ptrold 的值增?减少)了n ?br />sizeof(ptrold 所指向的类?个字节。就是说Qptrnew 所指向的内?br />区将比ptrold 所指向的内存区向高(?地址方向Ud了n ?br />sizeof(ptrold 所指向的类?个字节?br />指针和指针进行加减:
两个指针不能q行加法q算Q这是非法操作,因ؓq行加法后,得到?br />l果指向一个不知所向的地方Q而且毫无意义。两个指针可以进行减?br />操作Q但必须cd相同Q一般用在数l方面,不多说了?br />

David Lee 2008-08-31 22:19 发表评论
]]>
Ʒ99þþþþ鶹| þseֻоƷ| þþwww| þ99þ99Ʒӿ| þþƷav| ݺݸɺݺݾþ| ŷƷƵһþþþƷ| 뾫Ʒþһ | 2021ٸþþþþþþþ| þ99Ʒ| þþƷŷպ| һһþAþۺϾƷ | þþƷ99þ޶| þ99Ʒ99þ| ޾Ʒרþͬ| þɧ| ҹ91þø| רþۺϾĻ| Ʒþþþþù| ޾Ʒþþþþο| Ʒþþþþþö| պһþ| ŷ þ| ɫþþþþþС˵ | ݺɫۺϾþ| ޹徫Ʒ߾þ| þùƷ99þþþþ| ޾ƷۺϾþ| 99þùۺϾƷӰԺ| vaĻþ| ҹӰԺþþƷѿһ | 97Ʒ˾þþô߽| ˾Ʒһþ| þҹɫƷվ| þֹۺ޾Ʒ| þþƷר| þþƷ99͵| þˬˬƬAV| þۺ97ɫֱ| Ʒþþþþù| Ʒþþþþ|