??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久精品国产免大香伊 ,日本一区精品久久久久影院,国产亚洲美女精品久久久http://www.shnenglu.com/Fox/archive/2010/01/07/105053.htmlFoxFoxWed, 06 Jan 2010 17:32:00 GMThttp://www.shnenglu.com/Fox/archive/2010/01/07/105053.htmlhttp://www.shnenglu.com/Fox/comments/105053.htmlhttp://www.shnenglu.com/Fox/archive/2010/01/07/105053.html#Feedback0http://www.shnenglu.com/Fox/comments/commentRss/105053.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/105053.html本文同步?a mce_ target="_blank">游戏人生

最q有点忙Q本来要用autoconf+automake把自q代码梳理一下的Q因为工作停了近两周?/p>

本想看看有什么工具可以自动生成Makefile.amQ答案是Q?a mce_ target="_blank">Automake不支持通配W,而且q口口声壎ͼ振振有词。既然说的这么言词凿凿,情深意切Q我x也没有必要用shell生成Makefile.am了?/p>

用着用着Q我有点怀疑h生了Q不知道什么时候需要用autoconf和automake。如果我只是qx自己写一些toy codes的话Q感觉用autoconf和automake有点大炮打蚊子的感觉Q而且每次新加代码或者是U除代码、甚x更改目录Q都要重新执? autoconf、automakeQ不知道我说的对与不对)。对于一个大型项目,执行一ơconfigure和make是很痛苦的一件事Qmake的中 间目标文件或者库文g、执行文件倒是不一定非得完全rebuildQconfigure的配|检查呢Q是不是也有cM机制Q反正我在用ogre或? cegui的时候,每次执行./configure是重新配|了的?/p>

实际在开源项目里面也不可能维护两套makefile吧?/p>

看了一?a mce_ target="_blank">googletest的配|,倒是清爽的很Q最大的特点是只有一个Makefile.amQ这样在一个项目里面只需要维护一个Makefile.am够了?/p>

cegui比较常规Q每个子目录都会l护一个Makefile.am?/p>

需要特别注意的是ogre?a mce_ target="_blank">1.7.0开始已l开始?a mce_ target="_blank">cmake?#8230;…

请听题:理中小型项目,你們֐于下面哪个工P

o makeQ钻木取火,玩的是个技术,~译代码Q只用装B的,不用牛B的,你要是用什么cmakeQ你都不好意思跟别h打招|q么l典的东西,_N需要多久?要我说怎么着也得个把俩月吧,个把俩月Q那是入门,臛_半年Q就q还得有Feldman的悟性,不舍昼夜Q?/p>

o autoconf+automakeQ既有群众基Q又有技术含量,你是那样拉蘪的男人,不管在什么地方,好像漆黑中的萤火虫一P那样的鲜明,那样? Z。你那忧郁的眼神Q稀嘘的胡喳子,乎其技的指法;既可以ȝ原始人的生力低下,q可以鄙视现代h的不学无术?/p>

o cmakeQ在MSVCers面前抬不起头Q在UNIXers面前g更抬不v_而cmake对WINDOWS和UNIXq_的完支持,以让所有的 MSVCers和UNIXer在你面前抬不起头Q你是公鸡中的战斗机。所以你q是可以N气昂的丢下一句:走NB的\Q让SB说去吧?/p>




Fox 2010-01-07 01:32 发表评论
]]>
Autotools初体?/title><link>http://www.shnenglu.com/Fox/archive/2009/12/23/autotools_first_use.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Tue, 22 Dec 2009 18:18:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2009/12/23/autotools_first_use.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/103743.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2009/12/23/autotools_first_use.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/103743.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/103743.html</trackback:ping><description><![CDATA[     摘要: 从接触和使用make以来Q前前后后写了不MakefileQ添d减、修修补补,累计上千行是有的Q,今天在重新整理代码的l织l构之后Q突然就惻I我ؓ什么不使用Autotools呢? <br> <br>在开始体验功能强大的Autotools之前Q简单(详细Q回忆ȝ一下我使用make的经历和思考的q程Q反省一下看看自己在接触q些新鲜事物的时候到底走了多弯路?nbsp; <a href='http://www.shnenglu.com/Fox/archive/2009/12/23/autotools_first_use.html'>阅读全文</a><img src ="http://www.shnenglu.com/Fox/aggbug/103743.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2009-12-23 02:18 <a href="http://www.shnenglu.com/Fox/archive/2009/12/23/autotools_first_use.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACE vs Boost: Singleton的实?/title><link>http://www.shnenglu.com/Fox/archive/2009/09/22/96898.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Mon, 21 Sep 2009 16:38:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2009/09/22/96898.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/96898.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2009/09/22/96898.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/96898.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/96898.html</trackback:ping><description><![CDATA[<p>本文同步?a target="_blank">游戏人生</a> <p>以前曄讨论q?a target="_blank">Singleton的实?/a>Q这ơ在对照ACE和Boost代码的时候,又重新审视了一下二者对Singleton不同的实现。其间的差别也体C不同的编E哲学:ACE的实现更加偏重多U程中的安全和效率问题;Boost的实现则偏重于用语a自n的特性满Singleton模式的基本需求? <p><strong>o ACE的实?/strong> <p>Douglas C. Schmidt?a target="_blank">Double-Checked Locking: An Optimization Pattern for Efficiently Initializing and Accessing Thread-safe Objects</a>一文中对double-check lockQ一般译为双锁)q行了详l的阐述? <p>ACE的Singleton使用Adapter模式实现对其他类的适配Q之具有全局唯一的实例。由于C++标准q明确指定全局静态对象的初始化顺序,ACE使用double-check lock保证U程安全Qƈ使之不受全局静态对象初始化序的媄响,同时也避免了全局静态实现方式的初始化后不用的开销? <p>如果你能够准的区分以下三种实现的弊端和隐患Q对double-check lock也就有了_的了解? <blockquote><code> <p>// -------------------------------------------<br>class Singleton<br>{<br>public:<br>    static Singleton *instance (void)<br>    {<br>        // Constructor of guard acquires<br>        // lock_ automatically.<br>        Guard<Mutex> guard (lock_);<br>        // Only one thread in the<br>        // critical section at a time.<br>        if (instance_ == 0)<br>            instance_ = new Singleton;<br>        return instance_;<br>        // Destructor of guard releases<br>        // lock_ automatically.<br>    }<br>private:<br>    static Mutex lock_;<br>    static Singleton *instance_;<br>}; <p>// ---------------------------------------------<br>static Singleton *instance (void)<br>{<br>    if (instance_ == 0) {<br>        Guard<Mutex> guard (lock_);<br>        // Only come here if instance_<br>        // hasn’t been initialized yet.<br>        instance_ = new Singleton;<br>    }<br>    return instance_;<br>} <p>// ---------------------------------------------<br>class Singleton<br>{<br>public:<br>    static Singleton *instance (void)<br>    {<br>        // First check<br>        if (instance_ == 0)<br>        {<br>            // Ensure serialization (guard<br>            // constructor acquires lock_).<br>            Guard<Mutex> guard (lock_);<br>            // Double check.<br>            if (instance_ == 0)<br>                instance_ = new Singleton;<br>        }<br>        return instance_;<br>        // guard destructor releases lock_.<br>    }<br>private:<br>    static Mutex lock_;<br>    static Singleton *instance_;<br>};</p></code></blockquote> <p>更多详情Q见Schmidt老师的原文和ACE_Singleton实现? <p><strong>o Boost的实?/strong> <p>Boost的Singleton也是U程安全的,而且没有使用锁机制。当ӞBoost的Singleton有以下限Ӟ遵从q些限制Q可以提高效率)Q? <p>o The classes below support usage of singletons, including use in program startup/shutdown code, AS LONG AS there is only one thread running before main() begins, and only one thread running after main() exits. <p>o This class is also limited in that it can only provide singleton usage for classes with default constructors. <blockquote><code> <p>// T must be: no-throw default constructible and no-throw destructible<br>template <typename T><br>struct singleton_default<br>{<br>private:<br>    struct object_creator<br>    {<br>        // This constructor does nothing more than ensure that instance()<br>        //  is called before main() begins, thus creating the static<br>        //  T object before multithreading race issues can come up.<br>        object_creator() { singleton_default<T>::instance(); }<br>        inline void do_nothing() const { }<br>    };<br>    static object_creator create_object; <p>    singleton_default(); <p>public:<br>    typedef T object_type; <p>    // If, at any point (in user code), singleton_default<T>::instance()<br>    //  is called, then the following function is instantiated.<br>    static object_type & instance()<br>    {<br>        // This is the object that we return a reference to.<br>        // It is guaranteed to be created before main() begins because of<br>        //  the next line.<br>      static object_type obj; <p>      // The following line does nothing else than force the instantiation<br>      //  of singleton_default<T>::create_object, whose constructor is<br>      //  called before main() begins.<br>      create_object.do_nothing(); <p>      return obj;<br>    }<br>};<br>template <typename T><br>typename singleton_default<T>::object_creator<br>singleton_default<T>::create_object;</p></code></blockquote> <p>对于多数Singleton使用QBoost提供的版本完全能够满需求。ؓ了效率,我们有必要对其用作Z定的限制?/p> <p>而在多线E编E中Q则有必要用double-check lock降低频繁加锁带来的开销?/p> <p>-------------------------------------------------------------------------------</p> <p>PS: ƣ赏Soft的一句话Q?strong>l得赯惑,耐得住寂?/strong>?/p><img src ="http://www.shnenglu.com/Fox/aggbug/96898.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2009-09-22 00:38 <a href="http://www.shnenglu.com/Fox/archive/2009/09/22/96898.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IOCP使用时常见的几个错误http://www.shnenglu.com/Fox/archive/2009/09/12/95975.htmlFoxFoxFri, 11 Sep 2009 16:20:00 GMThttp://www.shnenglu.com/Fox/archive/2009/09/12/95975.htmlhttp://www.shnenglu.com/Fox/comments/95975.htmlhttp://www.shnenglu.com/Fox/archive/2009/09/12/95975.html#Feedback1http://www.shnenglu.com/Fox/comments/commentRss/95975.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/95975.html本文同步?a target="_blank">游戏人生

在用IOCPӞ最重要的几个API是GetQueueCompeltionStatus、WSARecv、WSASendQ数据的I/O及其完成状态通过q几个接口获取ƈq行后箋处理?/p>

GetQueueCompeltionStatus attempts to dequeue an I/O completion packet from the specified I/O completion port. If there is no completion packet queued, the function waits for a pending I/O operation associated with the completion port to complete.

BOOL WINAPI GetQueuedCompletionStatus(
  __in   HANDLE CompletionPort,
  __out  LPDWORD lpNumberOfBytes,
  __out  PULONG_PTR lpCompletionKey,
  __out  LPOVERLAPPED *lpOverlapped,
  __in   DWORD dwMilliseconds
);

If the function dequeues a completion packet for a successful I/O operation from the completion port, the return value is nonzero. The function stores information in the variables pointed to by the lpNumberOfBytes, lpCompletionKey, and lpOverlapped parameters.

除了兛_q个API的in & outQ这是MSDN开头的几行可以告诉我们的Q之外,我们更加兛_不同的return & out意味着什么,因ؓ׃各种已知或未知的原因Q我们的E序q不L有正的return & out?/p>

If *lpOverlapped is NULL and the function does not dequeue a completion packet from the completion port, the return value is zero. The function does not store information in the variables pointed to by the lpNumberOfBytes and lpCompletionKey parameters. To get extended error information, call GetLastError. If the function did not dequeue a completion packet because the wait timed out, GetLastError returns WAIT_TIMEOUT.

假设我们指定dwMilliseconds为INFINITE?/p>

q里常见的几个错误有Q?/p>

WSA_OPERATION_ABORTED (995): Overlapped operation aborted.

׃U程退出或应用E序hQ已攑ּI/O 操作?/p>

MSDN: An overlapped operation was canceled due to the closure of the socket, or the execution of the SIO_FLUSH command in WSAIoctl. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.

成因分析Q这个错误一般是׃peer socket?strong>closesocket或?strong>WSACleanup关闭后,针对q些socket的pending overlapped I/O operation被中止?/p>

解决ҎQ针对socketQ一般应该先调用shutdown止I/O操作后再调用closesocket关闭?/p>

严重E度Q?strong>d易处?/strong>?/p>

WSAENOTSOCK (10038): Socket operation on nonsocket.

MSDN: An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.

成因分析Q在一个非套接字上试了一个操作?/p>

使用closesocket关闭socket之后Q针对该invalid socket的Q何操作都会获得该错误?/p>

解决ҎQ如果是多线E存在对同一socket的操作,要保证对socket的I/O操作逻辑上的序Q做好socket的graceful disconnect?/p>

严重E度Q?strong>d易处?/strong>?/p>

WSAECONNRESET (10054): Connection reset by peer.

q程L关闭了一个现有的q接?/p>

MSDN: An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.

成因分析Q在使用WSAAccpet、WSARecv、WSASend{接口时Q如果peer applicationH然中止Q原因如上所qͼQ往其对应的socket上投递的operations会p|?/p>

解决ҎQ如果是ҎL或程序意外中止,那就只有各安天命了。但如果q程序是你写的,而你只是hard closeQ那q不得别h了。至,你要知道q样的错误已l出CQ就不要再费劲的l箋投递或{待了?/p>

严重E度Q?strong>d易处?/strong>?/p>

WSAECONNREFUSED (10061): Connection refused.

׃目标机器U极拒绝Q无法连接?/p>

MSDN: No connection could be made because the target computer actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host—that is, one with no server application running.

成因分析Q在使用connect或WSAConnectӞ服务器没有运行或者服务器的监听队列已满;在用WSAAcceptӞ客户端的q接h被condition function拒绝?/p>

解决ҎQCall connect or WSAConnect again for the same socket. {待服务器开启、监听空闲或查看被拒l的原因?strong>是不是长的丑或者钱没给够,要不是服务器拒l接受天仯酬自d业去了?

严重E度Q?strong>d易处?/strong>?/p>

WSAENOBUFS (10055): No buffer space available.

׃pȝ~冲区空间不x列队已满Q不能执行套接字上的操作?/p>

MSDN: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.

成因分析Q这个错误是我查看错误日志后Q最在意的一个错误。因为服务器对于消息收发有明限Ӟ如果~冲Z_该早处理了Q不可能待到send/recvp|啊。而且q个错误在之前的版本中几乎没有出现过。这也是q篇文章的主要内宏V像connect和accept因ؓ~冲区空间不都可以理解Q而且危险不高Q但如果send/recv造成拥堵q恶性@环下去,ȝ大了,臛_说明之前的验证逻辑有疏漏?/p>

WSASendp|的原因是QThe Windows Sockets provider reports a buffer deadlock. q里提到的是buffer deadlockQ显然是׃多线EI/O投递不当引L?/p>

解决ҎQ在消息收发前,Ҏ大挂L消息ȝ数量和容量进行检验和控制?/p>

严重E度Q?strong>严重?/p>

本文主要参?a target="_blank">MSDN?/p>

************* 说明 *************

Fox只是对自己关心的几个错误和API参照MSDNq行分析Q不提供额外帮助?/p>

Fox 2009-09-12 00:20 发表评论
]]>
Amdahl 定律 = Gustafson定律http://www.shnenglu.com/Fox/archive/2009/09/10/95782.htmlFoxFoxThu, 10 Sep 2009 04:04:00 GMThttp://www.shnenglu.com/Fox/archive/2009/09/10/95782.htmlhttp://www.shnenglu.com/Fox/comments/95782.htmlhttp://www.shnenglu.com/Fox/archive/2009/09/10/95782.html#Feedback0http://www.shnenglu.com/Fox/comments/commentRss/95782.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/95782.html本文同步?a target="_blank">游戏人生

周伟明老师应该是多核计领域的老h了?/p>

q几日因为想找找无锁Qlock-freeQ方面的信息Q就打开?a target="_blank">周老师的blog。看?a target="_blank">多核pȝ中三U典型锁竞争的加速比分析q篇文章Ӟ觉得老师多核计算效率是有必要的,但拿Amdahl 定律和Gustafson定律作对比有点不恰当?/p>

按照我的理解Q这两个定律所ȝ的内Ҏ完全一致的Q只是对加速比的定义不一LŞ了。这里,我们都以S(n)表示n核系l对具体E序的加速比QK表示串行部分计算旉比例?/p>

Amdahl 定律的加速比QS(n) Q?使用1个处理器的串行计时?/ 使用n个处理器的ƈ行计时?/p>

S(n) = 1/(K+(1-K)/n) = n/(1+(n-1)K)

Gustafson定律的加速比QS(n) Q?使用n个处理器的ƈ行计量 / 使用1个处理器的串行计量

S(n) = K+(1-K)n

通俗的讲QAmdahl 定律工作量看作1Q有n怹只能分担1-K的工作量Q而Gustafson定律则将单核工作量看?Q有n核,可以增加n(1-K)的工作量?/p>

q两个计公式都没有锁开销考虑在内Q是理想化的。周老师提到设计不当造成q行变串行的问题与这两个公式计算无关。因ZQ何多核计都存在对串行和q行的设计考量Q这正是E序员在使用多核q行时最兛_的事情?/p>

MQ二者的区别只在于态度的不同:一个消极悲观,一个积极乐观,充其量是一个冷W话Q而于多核计算没有M兌?/p>

我说q些也与多核计算没有兌Q丝毫没有质疑多核效率的意思。相反,我期待能够通过技术层面提高多核的有效负蝲?/p>最后一句题外话Q周老师使用Word的水q一般:所有来自Word的截N是在面视图直接截,换行W和光标随处可见?img src ="http://www.shnenglu.com/Fox/aggbug/95782.html" width = "1" height = "1" />

Fox 2009-09-10 12:04 发表评论
]]>
ACE: Socket装Q?1Q?/title><link>http://www.shnenglu.com/Fox/archive/2009/09/01/94973.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Tue, 01 Sep 2009 06:22:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2009/09/01/94973.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/94973.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2009/09/01/94973.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/94973.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/94973.html</trackback:ping><description><![CDATA[<p>本文同步?a target="_blank">游戏人生</a></p> <p><strong>o *__ ?__* o</strong></p> <p>在阅读ACE代码和C++NPv1, v2, APG的时候,我意识到一个问题:虽然E有C++和网l基的同学都可以LACEQ但如果你对OSQ五大管理模块都包含在内Q、TCP/IP、C++、Design Patterns了解多Q你p能体会ACEZ么需要这么庞杂,虽然它不够完(但至我q没有资格来批评q一点,我现在最常想做的一个动作就是五体投圎ͼ?/p> <p>而且我隐U感觉到Q我现在所写的很多东西在以后(对于有些人或许就是现在)看来会相当不深刻、相当不严}Q但对于一D学习历E,q个q程是必然的、必需的?/p> <p>在C++NPv1中,<a target="_blank">Douglas C. Schmidt</a>把原始socket及其API的缺h些妖化了,比如一D加上注释、空行在内的35行的代码Q被指出?0处错误之多。这像很多其他语言的倡导者或反传lC/C++指针者在批评指针时的说法一栗长期用原始socket和指针的同学Ҏ感觉很不舒服Q何况socket API提供了大量错误检的接口Q至多是不够友好|了。你好就好了Q没必要抓住别h一痛批吧Q『本是同根生Q相煎何太急』?/p> <p>虽然Solaris、Linux的很多版本及Windows对v源于Berkeley的socket APIq行了重写,但不可否认,׃历史原因和POSIX标准的存在,对于使用者而言Q我们可以无视这些API的实现差异。只是一旦我们从socket通信扩展到其他IPC通信的话Q就需要正视各UI/Ol节的差异了?/p> <p>׃UNIX中,对于socket, file, pipe, device的大多数操作Q描q符都是通用的(q一点,OS上面讲的更清楚些Q。而Windows中,句柄大多不能互换Qsocket对于MS来说是舶来品Q。系l和标准的不一致导致地址、协议和API的؜杂甚x؜乱?/p> <p>UNIX下的描述W和Windows的句柄可以看作是同一个概念,只是应用环境不一P所描述的内容也时常不一P再简单了_它们都是一个整型的ID?/p> <p>ACE的源码中使用了大量预处理指oQ尤其在跨^?~译环境的部分更加明显。鉴于C/C++标准的博大胸怀Q有些指令需要阅ȝ关编译器提供的帮助文档:</p> <p>o #pragma: <a target="_blank">GCC</a>, <a target="_blank">MSVC</a></p> <p>o #define (#, #@, ##) : <a target="_blank">GCC</a>, <a target="_blank">MSVC</a> </p> <p>其中有若q代码文件以.inl为后~Q里面是寚w分函数的内联实现Q以使代码结构看上去更加z。如果确定用内联函数的话,*.inl被包含?.h的最后,如果不用,则像*.h一P包含?.cpp的头部?/p> <p>ACE采用doxygen输出文档Q在阅读代码注释时能够感受到差异Q但基本不会影响阅读?/p> <p><strong>o * __ 关于W?章(C++NPv1Q__ * o</strong></p> <p>ACE抽象的地址cACE_Addr拥有ACE_DEV_Addr, ACE_FILE_Addr, ACE_INET_Addr, ACE_SPIPE_Addr, ACE_UNIX_Addr五个子类。对于狭义上的网l通信QTCP/IPQ而言QACE_INET_Addr对应于我们熟悉的sockaddr_in?/p> <p>ACE_IPC_SAP是IPCQinterprocess communicationQI/O操作cȝrootcR?/p> <p>从编码的角度看,q个cL亮的地方在于CZ了抽象类的另一U实现方式?/p> <p>一提到抽象c,大多Ch的第一反应是pure virtual function。当一个基cȝ定需要用virtual functionӞq是一个不错的选择。但我们都知道虚拟函数有开销。而且对于一个结构简单的抽象基类和其l承子类Q尤其是大量使用ӞQ一个虚函数表带来的开销会让整个设计昑־十分y脚?/p> <p>我们都知道如何强制让一个类无法使用default constructorQprotectedQ。如果对基类使用该方法,仅子类hpublic的default constructorQ这pC定义抽象基类的效果?/p> <p>virtual destructor的意义在于防止delete父类指针Q指向子cd象)时未调用子类destructor。在此例中,为避免这U情况,同样destructor声明为protected卛_?/p> <p>从设计实现的角度看,相较于socket APIQACE_IPC_SAP的子cACE_SOCK提供了编译时对句柄合法性的?/p> <p>从逻辑功能层面划分Qsocket有三U角Ԍ</p> <p>o active connection role (connector)Q主动连?/p> <p>o passive connection role (acceptor)Q被动连?/p> <p>o communication role (stream)Q数据通信</p> <p>但socket API毕竟不是OOD出来的,对于一个socket描述W,也完全没有必要去限制其担负的功能Q更不可能搞成三U不同的socket。而OOD的ACE则可以轻易实现对socket对象及其操作的封装?/p> <p>工厂cACE_SOCK_Connector是一个主动创建通信端的工厂cRsocket API中的connect接口只是Z个socket建立与其它peer的网l连接,而不产生新的socket实例Q也不依赖于M其它socket。同PACE_SOCK_Connector只是Z个ACE_SOCK_Stream对象Q对用于数据通信的socket的封装)q接到ACE_AddrQ对struct sockaddr的封装)提供接口Q也不含对ACE_SOCK_Stream对象的其它操作?/p> <p>工厂cACE_SOCK_Acceptor是一个被动创建通信端的工厂cR当监听到新的网l连接后Qؓ该连接初始化一个ACE_SOCK_Stream对象。和connector不同的是Qacceptor依赖于一个已l存在的充当监听功能的socket句柄QACE_SOCKQ,因此QACE_SOCK_Acceptor是ACE_SOCK的一个子cR?/p> <p>ACE_SOCK_Stream是只负有通信传输功能的socketQ对应connection-oriented的TCP通信格式streamQ和UDP的CE_SOCK_CODgram相呼应。ACE_SOCK_Stream只是socket的通信载体Q在两个工厂ACE_SOCK_Connector和ACE_SOCK_Acceptor中初始化。这样一个类除支持最基本的数据发送(sendQ和接收QrecvQ和dQblockingQ、非dQnonblockingQ及定时QtimedQ的I/O模式外,q支持分散读取(scatter-readQ和集中写入Qgather-writeQ?/p> <p>对于一个简单的『网l课E作业:写一个有q接的IM程序』,上面q些内容已经_了。当然即使用对应的几个socket API也已l够了。但我们昄更加兛_如此庞大的一个库Q是如何解决复杂的网l应用的Q我其兛_的是多线Eƈ发如何更好的处理?/p> <p>所以,我准备跑到第8?章了?/p><img src ="http://www.shnenglu.com/Fox/aggbug/94973.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2009-09-01 14:22 <a href="http://www.shnenglu.com/Fox/archive/2009/09/01/94973.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Doxygen在Cygwin下的使用http://www.shnenglu.com/Fox/archive/2009/08/28/94689.htmlFoxFoxFri, 28 Aug 2009 09:14:00 GMThttp://www.shnenglu.com/Fox/archive/2009/08/28/94689.htmlhttp://www.shnenglu.com/Fox/comments/94689.htmlhttp://www.shnenglu.com/Fox/archive/2009/08/28/94689.html#Feedback2http://www.shnenglu.com/Fox/comments/commentRss/94689.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/94689.html本文同步?a target="_blank">游戏人生

我发现我最q成了Cygwin下的白鼠,写完Cygwin下安装ACEQ写ACE在cygwin下的使用。现在又?a target="_blank">doxygen?/p>

之前提到在Cygwin下读代码的不习惯Q后来回到VS下看。没q几天,觉得VS下还是不够直观,于是q接看ACE的doxygen?#8230;…

doxygen好是好,用v来还是要慢慢习惯才行Q需要在写注释和代码的时候注意一些,掌握的细节和技巧越多,出来的文档越丰富Q当Ӟq和代码质量是两码事Q?/p>

我自然是把doxygen安装在Cygwin下了Q由于doxygen没有提供infoQInfo doxygen时就自动打开了doxygen的manQ和man doxygen、doxygen --help一个效果?/p>

如果希望阅读更详的使用ҎQ只有自?a target="_blank">down一个manual?/a>?/p>

在Cygwin下,doxygen采用GNU的libiconvq行文字~码的{换,?a target="_blank">UTF-8作ؓ默认~码?/p>

使用doxygen生成config-file模板后,可以在config-file中进行一些项目设|(有注释的Q看的懂Q?/p>

Z支持中文Q我DOXYFILE_ENCODING用的?a target="_blank">EUC-CNQ但输出文档的语aOUTPUT_LANGUAGE却选了English。两点原因:

o EUC-CNQ各U汉字编码知识就不在此普及了Q你可以认ؓ体字~码都是EUC-CNQ和UTF-8不同Q但OUTPUT_LANGUAGE的各U语a都是使用的UTF-8Q?span style="text-decoration: line-through;">所以两U编码不可能同时昄Q当Ӟ你可以把EUC-CN全{成UTF-8。编码不是高U的技术,但对于非p用户l对是一个噩?/span>Q?span style="color: rgb(34, 34, 34); font-family: Georgia, Arial; font-size: 14px; ">后来发现是我自己学艺不精QDOXYFILE_ENCODING只是配置文g的编码格式而已Q而识别中文文档只需要修改INPUT_ENCODING成EUC-CN卛_QOUTPUT_LANGUAGE自然讄成Chinese也不会有问题Q因为doxygen采用UTF-8输出Q用中文输Z会有q问题?/span>

o 虽然我的英文很蹩脚,虽然我的文档中多有中文注释。但像doxygen中文输出的文档中把class、public都给你翻译成中文Q你也受不了Q这也英文水qx兟?/p>

config-file中的其他内容我现在也用不刎ͼ没有仔l看?/p>

因ؓKevin会在公司里讲一下doxygenQdoxygen的manual也讲的很详细Q我qҎ_不翻译文档了?/p>

单的一?a target="_blank">Doxygen的测?/a>在这里?/p>

Fox 2009-08-28 17:14 发表评论
]]>
ACE之Cygwin vs Winhttp://www.shnenglu.com/Fox/archive/2009/08/24/94234.htmlFoxFoxMon, 24 Aug 2009 03:59:00 GMThttp://www.shnenglu.com/Fox/archive/2009/08/24/94234.htmlhttp://www.shnenglu.com/Fox/comments/94234.htmlhttp://www.shnenglu.com/Fox/archive/2009/08/24/94234.html#Feedback6http://www.shnenglu.com/Fox/comments/commentRss/94234.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/94234.html本文同步?a target="_blank">游戏人生

我屈服了Q还是VS用的方便?/p>

之前在Cygwin下已l可以用的ACEQ因为阅M码太不方便(对于一个WinEr来说Q,上午在VS下面׃几分钟就把ACE配好了,而且使用$(ACE_ROOT)\examples\C++NPv1的代码跟t调试,太习惯了?/p>

按照$(ACE_ROOT)\ACE-INSTALL.html的安装说明:

o 选择q打开$(ACE_ROOT)\ace\ace_vc9.sln

o dconfig.hq加入以下内容:

   #define ACE_HAS_STANDARD_CPP_LIBRARY 1
    #include "ace/config-win32.h"

o F7

-----------------------------------------------

OKQ现?(ACE_ROOT)\lib下面已经生成了ACEd.dll、ACEd.libQ再讄一下系l环境变量(q行E序必需Q和VC++目录Q调试程序必需Q。可以用了Q?

o 选择q打开$(ACE_ROOT)\examples\C++NPv1

o F7

o

Fox 2009-08-24 11:59 发表评论
]]>
ACE在cygwin下的使用http://www.shnenglu.com/Fox/archive/2009/08/19/93781.htmlFoxFoxWed, 19 Aug 2009 02:05:00 GMThttp://www.shnenglu.com/Fox/archive/2009/08/19/93781.htmlhttp://www.shnenglu.com/Fox/comments/93781.htmlhttp://www.shnenglu.com/Fox/archive/2009/08/19/93781.html#Feedback3http://www.shnenglu.com/Fox/comments/commentRss/93781.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/93781.html本文同步?a target="_blank">游戏人生

int ACE_TMAIN(int, ACE_TCHAR *[])
{
     ACE_TRACE(ACE_TEXT("main"));

     ACE_DEBUG((LM_INFO, ACE_TEXT("%IStart\n")));
     ACE_DEBUG((LM_INFO, ACE_TEXT("%IEnd\n")));

     return 0;
}

/*--------- makefile ---------*/

BIN     = hello                       # src & exe file name
SRC     = $(addsuffix .cc, $(BIN))    # src file suffix
LIBS    = -lACE                       # libACE.dll under cygwin

include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
include $(ACE_ROOT)/include/makeinclude/macros.GNU
include $(ACE_ROOT)/include/makeinclude/rules.common.GNU
include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU
include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU
include $(ACE_ROOT)/include/makeinclude/rules.local.GNU

/*--------- Compilation ---------*/

GNUmakefile: /home/fox/ace/GNUmakefile MAKEFLAGS=k

g++ -Wpointer-arith -mthreads -mtune=pentiumpro -O3 -g -pipe    -pipe   -I/usr/\
share/ace -DACE_HAS_EXCEPTIONS -DACE_NO_INLINE  -c -o .obj/hello.o hello.cc
g++ -Wpointer-arith -mthreads -mtune=pentiumpro -O3 -g -pipe    -pipe   -I/usr/\
share/ace -DACE_HAS_EXCEPTIONS -DACE_NO_INLINE  -Wl,--enable-auto-import -Wl,-E\
-L/usr/share/ace/lib -o hello .obj/hello.o  -lACE

Compilation finished at Wed Aug 19 00:35:42

/*--------- Result ---------*/

$ ./hello.exe
(14417928) calling main in file `hello.cc' on line 13
    Start
    End
(14417928) leaving main

-------------------------------------------------------

更多内容请参?a target="_blank">C++NP(C++ Network Programming) vol.1 & vol.2和APG(The ACE Progrmmer's Guide)?/p>

忙活了一晚上Q终于知道怎么包含头文件了Q在gcc的编译选项中用 -I?I$(ACE_ROOT)Q?/p>

本例中是Q?I/usr/share/ace

l果后面库又链接不上Q联想以前用OpenGL库的LIBSQ终于靠一?lACE搞定?/p>

因ؓ不愿意用MPCQL觉再多花些时间去弄又只是题更远了,有兴的同学自然是可以通过ACE的官|找到所有问题的{案?/p>

q样一来,ACE在cygwin下从安装C用也告一D落了,后面的问题就比较easy了,无非是你用ACE做什么。而我也不会再ACE && cygwin写什么心得了Qȝ见证了这两天的捣腾?/p>



Fox 2009-08-19 10:05 发表评论
]]>
与君共勉http://www.shnenglu.com/Fox/archive/2009/08/17/93620.htmlFoxFoxMon, 17 Aug 2009 08:31:00 GMThttp://www.shnenglu.com/Fox/archive/2009/08/17/93620.htmlhttp://www.shnenglu.com/Fox/comments/93620.htmlhttp://www.shnenglu.com/Fox/archive/2009/08/17/93620.html#Feedback4http://www.shnenglu.com/Fox/comments/commentRss/93620.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/93620.html本文同步?a target="_blank">游戏人生

现在有些q轻人的心态比较Qw,大致ȝ以下『四点表现』:

1. 眼高q顶Q?/p>

2. 垂手q膝Q?/p>

3. 期望值高Q?/p>

4. U极性低?/p>

深层ơ的客观原因大致是『四个没有』:

1. 没有吃过苦;

2. 没有q过z;

3. 没有说过话;

4. 没有当过家?/p>

一般都h『四个特征』:

1. 独生子女Q?/p>

2. 毕业ChQ?/p>

3. 沉默寡言Q?/p>

4. 半瓶开水?/p>

---------------------------------

1. 你想要什么?

参考:一个有影响力的人。(@李开?/a>Q?/p>

2. 那是否是你想要的Q?/p>

参考:你的眼光有多q,军_了你能走多远。(@FoxQ?/p>

3. 你需要做什么?

参考:高筑墙,q积_,~称王。(朱元璋)

4. 你还需要做什么?

参考:q_的心态,q取的态度Q坚定的目标Q不懈的努力。(@FoxQ?/p>

5. 你是否做CQ?/p>

参考:没有Q但我一直在努力。(@FoxQ?/p>

Fox 2009-08-17 16:31 发表评论
]]>
Cygwin下安装ACEhttp://www.shnenglu.com/Fox/archive/2009/08/17/93552.htmlFoxFoxMon, 17 Aug 2009 01:52:00 GMThttp://www.shnenglu.com/Fox/archive/2009/08/17/93552.htmlhttp://www.shnenglu.com/Fox/comments/93552.htmlhttp://www.shnenglu.com/Fox/archive/2009/08/17/93552.html#Feedback1http://www.shnenglu.com/Fox/comments/commentRss/93552.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/93552.html本文同步?a >游戏人生

-----------------------M-----------------------

《UNIX Network Programming?/a>很久了,只是q种愿望一直没有特别强烈。用的笔记本换了之后自己只是装了cygwinQ没有安装VSQ^时写些代码就只能在cygwin下用gcc了。最q对UNIX环境~程和网l基比较感兴,于是读这本书l于提上了议事日E,可是大多C店都没有q本书了?

工作之后Q对于自己喜Ƣ的书,很会ȝ电子版,觉得q是捧卷在手的感觉舒服一些,x么看怎么看,享受拿笔在上面写写画ȝ感觉。因此对于想MC到的书,W一反应是等待。在ȝ脑上面一些资料的时候才反应q来我已l很久没有downq电子书了,l果׃|上down?a target="_blank">很多惌(豆瓣)的书Qforgive me, Richard Stevens and anybody.

-----------------------动手-----------------------

之前只是在Windows下用qACEQ因为ACE提供了VS各种版本的解x案,~译q程比较单。这ơ放在cygwin下编译的时候,因ؓ环境变量讄问题Qƈ不是非常利Q参照了源码目录下的ACE-INSTALL.html的描q才问题解冟뀂现在将q程l出来,仅供google到这里的同学参考:

友情提示Q我目前对于cygwin和UNIXcȝl的了解停留在知其然Q还是在google之后Q的水^?

1. 增加环境变量

o 修改/etc/profile文gd属性:

$ chmod 777 /etc/profile

cygwin下的环境变量可以在该文g中配|,׃该文仉认具有写保护属性,因此需要修改之可写,修改完成之后应该记得对其q行写保护:

$ chmod 555 /etc/profile

o 打开profile文gQ本Z用emacsq行~辑Q读者也可以使用vi、vim{,在此不再赘述Q:

$ emacs /etc/profile

o 往profile中修改和d环境变量Q?

以下五行添加到文g中,ACE_ROOT为ACE源码目录Q本文用到的目录?usr/share/aceQ?

ACE_ROOT=/usr/share/ace
export ACE_ROOT

LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

# export PATH=$ACE_ROOT/ace:$PATH

q个操作{同于在VS下修改库文g目录Q我是直接修改了PATH变量的:

PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:$ACE_ROOT/ace:$PATH

o 执行/etc/profile

$ /etc/profile

执行修改后有可能需要重启cygwinQ可使用下面的命令查看ACE_ROOT讄是否正确Q?

$ echo $ACE_ROOT

2. 创徏若干文gQ?

o ?ACE_ROOT/ace 文g夹中创徏名ؓ config.h 的文Ӟq加入以下内容后保存关闭Q?

#include "ace/config-cygwin32.h"

o ?ACE_ROOT/include/makeinclude 文g夹中创徏名ؓ platform_macros.GNU 的文Ӟq加入以下内容保存关闭:

include $(ACE_ROOT)/include/makeinclude/platform_cygwin32.GNU

3. ~译ACEQ?

$ cd $ACE_ROOT/ace
$ make

大概会花掉十几分钟时间吧?

4. 试ACEQ?

$ cd $ACE_ROOT/tests
$ make

大概又会花掉十几分钟旉吧?

接下来就可以使用perl脚本完成所有测试,我没有用过perlQ时安装了一下?

$ perl run_test.pl

q个脚本在我一位同事的机器上跑了很久(十几分钟 or 几十分钟Q)Q不q的是,Windows竟然抛出了一个内存读写错误,更加不幸的是Q我现在没有能力ȝ定?

l果周末后面的时间又花在熟悉EMacs上了Q还没有看ACE的代码,只有下周才能看了?

-----------------------l束-----------------------

q种学生的东西拿出来讲实是很难ؓ情的Q然而,于我现在却又是极大的一个收莗真{我熟悉了其中的很多内容Q又未必会再有耐心说了。所以还是记录一下,既是鼓励Q也是督促?/p>

晚上睡觉之前M一?a target="_blank">《ACEE序员指南:|络与系l编E的实用设计模式?/a>Q发现里?.3节也讲到了怎么安装?/p>

Fox 2009-08-17 09:52 发表评论
]]>
设计模式Q四Q?amp;mdash;&mdash;Template Methodhttp://www.shnenglu.com/Fox/archive/2009/02/11/73420.htmlFoxFoxTue, 10 Feb 2009 17:46:00 GMThttp://www.shnenglu.com/Fox/archive/2009/02/11/73420.htmlhttp://www.shnenglu.com/Fox/comments/73420.htmlhttp://www.shnenglu.com/Fox/archive/2009/02/11/73420.html#Feedback1http://www.shnenglu.com/Fox/comments/commentRss/73420.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/73420.html在一个稍微上规模Q怎么也有几十个类吧)的C++E序中,l承和组合的使用比比皆是。虽然GoF提出了OOD的两个原则,W二个谓之?strong>优先使用对象l合Q而不是?/strong>』,但这l不意味着不用承,正因如此Q第一个原则才是?strong>针对接口~程Q而不是针对实现编E?/strong>』,q两个原则清楚的表达了Y件工E中?strong>低耦合』的思想?/p>

模板ҎQTemplate MethodQ的意图正是?strong>定义一个操作中的算法的框架Q而将一些步骤gq到子类?/strong>』?/p>

注意Q这里有个关键词『一些』,既然是『一些』,意味着父类的的接口中已l实C『一些』步骤,否则Q父cM只提供了抽象接口?/p>

q一情况是我们在~码时时帔R到的Q父cdC部分法中的通用行ؓQ子cL据自q需求可对其q行必要扩充?/p>

class CBase
{
public:
    // Default done
    virtual void Operation(void)
    {
        ...
    }
};

class CDerive :
    public CBase
{
public:
    virtual void Operation(void)
    {
        switch( ... )
        {
        case A: ...
        case B: ...
        case c: ...
        default:
            CBase::Operation();
        }
    }
};

因ؓ对父cȝ不了解或是对子类的太了解Q你以ؓCDerive::Operation()做了_多,不需?code>CBase::Operation()Q但实际上仍焉要的情况d发生?/p>

换一U方式,?code>Operation()作ؓ模板ҎQ把DoOperation()作ؓ可扩展的接口提供l子cd玎ͼ

class CBase
{
public:
    void SetFocus(void) { ... }
    void ResetFocus(void) { ... }
    // Call by user
    void Operation(void)
    {
        SetFocus();
        DoOperation();
        ResetFocus();
    }
    // Default done
    virtual void DoOperation(void) = 0;
};

class CDerive :
    public CBase
{
public:
    virtual void DoOperation(void)
    {
        ...
    }
};

模板Ҏ只是提供了一个简单的装技巧,当然不是所有的虚接口都q么?)?/p>


更多内容L?a target="_blank">我的个h主页?/p>

Fox 2009-02-11 01:46 发表评论
]]>
VS2005断点失效的问?/title><link>http://www.shnenglu.com/Fox/archive/2009/01/04/71110.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Sun, 04 Jan 2009 03:04:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2009/01/04/71110.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/71110.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2009/01/04/71110.html#Feedback</comments><slash:comments>19</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/71110.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/71110.html</trackback:ping><description><![CDATA[<p>VS2005下用VCQ部分断Ҏ效,昄『当前不会命中断炏V还没有文档加蝲MW号』?/p> <p>试过以下一些方法:</p> <p>1、无效断Ҏ在的目和启动项目的讄Q项?>属?>配置属?>C/C++->常规->调试信息格式Q这里不能ؓ『禁用』;</p> <p>2、项?>属?>配置属?>链接?>调试->生成调试信息Q这里设为『是』;</p> <p>3、C/C++->优化->优化选择『禁用』;</p> <p>4、删除解x案下?ncb文gQ?/p> <p>5、工?>选项->调试->『要求源文g与原始版本完成匹配』去掉勾Q?/p> <p>6、最后在上述讄的情况下Q重新编译整个解x案;</p> <p>7、回q头来,发现原来是一D不会被执行到的代码…?/p>看来Q除了VS本n会有bugQ自q代码q是要多查一下?img src ="http://www.shnenglu.com/Fox/aggbug/71110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2009-01-04 11:04 <a href="http://www.shnenglu.com/Fox/archive/2009/01/04/71110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单的属性结构设?/title><link>http://www.shnenglu.com/Fox/archive/2008/12/28/70542.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Sat, 27 Dec 2008 18:44:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/12/28/70542.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/70542.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/12/28/70542.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/70542.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/70542.html</trackback:ping><description><![CDATA[<p>本文最早发布于<a target="_blank">我的个h主页</a></p> <p>一般的RPG游戏中,玩家角色、NPC、物品、场景等一般都h为数众多的各U属性,使用C++~码Ӟ很容易考虑设计成ؓ大量的成员变量和相应的存取函敎ͼ</p><code> <p>class CObject<br>{<br>public:<br>    long GetAttrA(void) const { return m_lAttrA; }<br>    void SetAttrA(long lVal) { m_lAttrA = lVal; }<br>    long GetAttrB(void) const { return m_lAttrB; }<br>    void SetAttrB(long lVal) { m_lAttrB = lVal; }<br>    ...<br>    long GetAttrN(void) const { return m_lAttrN; }<br>    void SetAttrN(long lVal) { m_lAttrN = lVal; } <p>private:<br>    long m_lAttrA;<br>    long m_lAttrB;<br>    ...<br>    long m_lAttrN;<br>};</p></code> <p>乍一看,非常清晰明了。在一个稍昑֤杂的目中,惌住、甚x到每一个属性是非常隄Q况且除了属性,q有大量的逻辑处理Q甚x不同目间的数据交互Q比如将属性的数据库存取。这么做的缺点大致有q么几点Q?/p> <p>1. 属性没有明分门别c,其在多人协作、多模块~写Ӟ往往上面一扏V下面一批,甚至有重复属性、废弃属性,难于理和把握;</p> <p>2. 对于数据库存取,需要写单独的存取接口,而且一旦属性有增减、修改,存取接口要随之修改;</p> <p>3. 通过接口函数q行单的属性存取面临大量的堆栈保存Q即使用内联或宏定义,也是L不治本?/p> <p>针对上述问题Q我的思\也比较简单:?strong>基本cd</strong>数据q行二次装?/p><code> <p>struct tagDBAttrs<br>{<br>    long lA;<br>    long lB;<br>    ...<br>    long lN;<br>}; <p>class CObject<br>{<br>public:<br>    const tagDBAttrs& GetDBAttrs(void) const { return m_DBAttrs; }<br>    void SetDBAttrs(const tagDBAttrs& rDBAttrs)<br>    {<br>        memcpy(&m_DBAttrs, rDBAttrs, sizeof(m_DBAttrs));<br>    } <p>private:<br>    tagDBAttrs    m_DBAttrs;<br>    string        m_strA;<br>    CObject*      m_pObjB;<br>    CShape*       m_pShapeC;<br>    ...<br>};</code> </p> <p>之所以提到基本类型数据,主要~于基本cd构成的结构可以通过<code>sizeof</code>q算W直接确定,而像cd象等l合cdQ其深拷贝、赋倹{操作及赋值等逻辑则较为复杂,一般无法统一处理?/p> <p>以上面的<code>tagDBAttrs</code>ZQ对于基本类型数据处理具有非常大的优势,其在数据整体存取时Q此外,增减基本cd属性也比较单,而且不需要重?code>Get/Set</code>接口Q同时方便了对属性的分门别类处理?/p> <hr> <p>此处Z谈谈关于开发中的一些杂的体会?/p> <p>对于工作不久的同学而言Q拿C个Q务有可能出现以下两种情况Q?/p> <p>1. 以快速开发ؓ重,前期q展较快Q在型模块开发中风水Q但在面对复杂Q务时Q因为对前期设计重视不Q后期会不断调整代码Q甚臛_基本功能开发结束后Q因为逻辑架构问题Q导致bug隐患较多较深Q容易陷入惔|痛苦挣扎Q?/p> <p>2. 随时随处q求代码l构的优和执行效率的优化,_求精Q往往在前期设计上pq多的心思,以达到较合理的逻辑l构Q甚x延整个项目的开发进度,q种同学一般说来,代码质量较高Q后期bug较少?/p> <p>其实Q上面说的就是我自己Q我刚开始工作的时候,上面l我一个编写独立工LdQ当时急于表现Q缺乏项目实战经验,为编码而编码,逻辑l构不注重扩展性,设计不合理,在进行到后期Ӟ面对出现的新需求无法应对,D最后推到重来?/p> <p>后来Q慢慢接受了注重前期设计的观念,更因q完美情结和代码洁癖,不仅l常调整自己~码中不优美的片D,甚至俎代庖M改其他同事的代码Q追求处处的高效Q耗费大量旉_֊Q难以自拔?/p> <p>在Q何一个项目中Q都有轻重主ơ之分,也就是所谓的?strong>8020原则</strong>』,关于?strong>8020原则</strong>』怎么理解都行Q我的理解就是,每个目中的效率瓉?0%的核心代码,80%的时间和工作重心应该攑ֈq?0%的核心代码上。放C个小的模块中也是q样Q应该确定工作重心,在开发进度的限制下,Ҏ心代码精益求_,寚w效率瓉可以适当减少侧重?/p> <p>对于ChQ最隄是从整体的高度定20%的工作重心,q主要依赖于自n素质的提高和开发经验的U篏。而对需求深入细致的分析和对逻辑_求精的设计本w可以训l一个h分析问题、解决问题的能力?/p> <p>ȝ一下的话,也正是我们项目组历来所倡导和坚持的Q?/p> <p>1. _求精Q?/p>2. l节军_成|Q态度制约能力?img src ="http://www.shnenglu.com/Fox/aggbug/70542.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-12-28 02:44 <a href="http://www.shnenglu.com/Fox/archive/2008/12/28/70542.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式Q三Q?amp;mdash;&mdash;Singletonhttp://www.shnenglu.com/Fox/archive/2008/11/19/67339.htmlFoxFoxWed, 19 Nov 2008 15:37:00 GMThttp://www.shnenglu.com/Fox/archive/2008/11/19/67339.htmlhttp://www.shnenglu.com/Fox/comments/67339.htmlhttp://www.shnenglu.com/Fox/archive/2008/11/19/67339.html#Feedback4http://www.shnenglu.com/Fox/comments/commentRss/67339.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/67339.html不知道Singleton不用的最多的Q^时用的时候,往往都是直接敲下面一D:

……

不是不想改,是懒,敲多了已l不觉得q么写多费旉了,按大家的说法Q这样写臛_有这么几个缺点:

1. 必须在程序结束前手动释放Q这不仅是RP问题Q如果你借了内存不主动还Q说明你RP差,但被别h搞丢了(宕机Q导致你q不上,说明别hRP差?所以,q还是个问题Q?/p>

2. U程同步问题Q如果Singleton实例跨线E用,上例不安全,在Initial和Release时加锁可以解冻I

3. 最大的问题Q不能重用?/p>

阅读全文



Fox 2008-11-19 23:37 发表评论
]]>
设计模式Q二Q?amp;mdash;&mdash;Statehttp://www.shnenglu.com/Fox/archive/2008/11/19/67251.htmlFoxFoxTue, 18 Nov 2008 16:57:00 GMThttp://www.shnenglu.com/Fox/archive/2008/11/19/67251.htmlhttp://www.shnenglu.com/Fox/comments/67251.htmlhttp://www.shnenglu.com/Fox/archive/2008/11/19/67251.html#Feedback0http://www.shnenglu.com/Fox/comments/commentRss/67251.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/67251.htmlState模式对应到C++?strong>多?/strong>Ҏ?/p>

State模式适用较广Q这儿给出比较常见易懂的三种情况Q?/p>

1. 当怪物在面对不同职业和Ҏ的玩家时对应不同的AI处理和技能释放:

CSkill* pAttackSkill;

if( pPlayer->MagicImmune() ) pAttackSkill = SomePhysicalAttackSkill;

else if( pPlayer->PhysicalImmune() ) pAttackSkill = SomeMagicAttackSkill;

...

pAttackSkill->Begin();

...

或者用分支结构:

CSkill* pAttackSkill;

switch( pPlayer->GetOccupation() )

{

  case WARRIOR: pAttackSkill = SomeLongRangeSkill; break;

  case MAGICIAN: pAttackSkill = SomeForceSkill; break;

  case NIMROD: pAttackSkill = SomeMagicSkill; break;

...

}

pAttackSkill->Begin();

...

阅读全文



Fox 2008-11-19 00:57 发表评论
]]>
WSAEventSelect剖析http://www.shnenglu.com/Fox/archive/2008/10/27/65263.htmlFoxFoxMon, 27 Oct 2008 15:25:00 GMThttp://www.shnenglu.com/Fox/archive/2008/10/27/65263.htmlhttp://www.shnenglu.com/Fox/comments/65263.htmlhttp://www.shnenglu.com/Fox/archive/2008/10/27/65263.html#Feedback1http://www.shnenglu.com/Fox/comments/commentRss/65263.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/65263.html本文同时发布?a title="http://www.yulefox.com" target="_blank" rel="tag">http://www.yulefox.com?a title="http://www.shnenglu.com/fox" href="http://www.shnenglu.com/fox" target="_blank" rel="tag">http://www.shnenglu.com/fox?

q来在Windows下用WSAEventSelectӞ到一个棘手的问题Q当然现在已l解决了?

问题描述Q?/strong>

一个ServerQ一个ClientAQ一个ClientBQServer用WSAEventSelect模型监听Q只有监听,没有dQ,ClientA在连接Server后,ClientA对应的EventA被触发,Server的WSAWaitForMultipleEvents{待到EventAQClientBq接ServerӞTCP三次握手成功QClientB与Server的TCP状态被|ؓESTABLISHEDQ然而Server的WSAWaitForMultipleEvents没有{待到EventB被触发?

用netstat看了一下,ClientB与Server的状态是ESTABLISHEDQ此时如果ClientB退出,׃Server无法正常Close该连接,因此Server的状态不是TIME_WAIT而是CLOSE_WAITQ持l?时Q,Client的状态是FIN_WAIT_2Q持l?0分钟Q?

我尝试将ClientAd关闭后再ơ连接ServerQServer的WSAWaitForMultipleEvents在wait到EventA之后QEventB此时也被触发?

开始一直以为问题的Ҏ在于WSAEventSelect的用上Q毕竟,之前没有pȝ写过cM的代码,隑օ怀疑到事g模型的用上。多Ҏ阅资料,最后还是没有发现类似问题的解决Ҏ?

又跟了一上午之后QKevin开始怀疑是多线E用的问题Q我看了一下,的确没有对event的多U程操作q行处理Q但因ؓ在另一个应用中Q用了同样的模块,却没有该问题。最后考虑必要性时q是攑ּ了加临界资源Q无视多U程同步问题。Kevin本来劝我换个模型Q但我固执的认ؓ要做把q事儿做好。因Z午还要回学校一,想快搞定Q毕竟因一块已l把Kevin的进度拖了一周了Q心下还是过意不去,而且隐约感觉到离问题的解册来越q了?

问题分析Q?/strong>

在对着WSAWaitForMultipleEvents思考了半天之后Q忽然开H了Q如果ThreadA在WSAWaitForMultipleEventsӞ只有一个EventA被WSAEventSelectqset到signaled状态,则该EventA会被wait成功QThreadA处理EventA之后l箋d在WSAWaitForMultipleEvents。此ӞThreadB通过WSAEventSelectEventB初始化ؓnonsignaled状态,之后即EventB被set为signaled状态,但ThreadA的WSAWaitForMultipleEvents因ؓ处于d状态,不可能刷C仉Q也׃可能wait到EventBQ最l导致了ClientB的请求无法被响应。如果EventA被触发则会被ThreadA{待刎ͼWSAWaitForMultipleEventsq回后再ơ进入时事g集已l被hQEventB被waitC׃隄解了?

问题解决Q?/strong>

说到底是因ؓ当ThreadAd在WSAWaitForMultipleEvents处之Ӟ事g集的变更无法立即得到体现。如果允怸层应用随时create或close一些eventQ则WSAWaitForMultipleEvents׃应该无限d下去?

因此最后的一个解x法就是让WSAWaitForMultipleEvents时q回qSleep一D|_当WSAWaitForMultipleEvents再次q入时事仉得以更新?

想了一下,另一个应用中之所以没出现该问题也只是个y合,因ؓ该应用中ThreadB的两ơWSAEventSelect间隔很短Q在ThreadA获得旉片之前已l确定了事g集?

说白了这也不是一个什么大问题Q甚臌不上M隑ֺQ但是因Z前对WSAEventSelect没有一个清晰的概念Q因此在发现和分析问题上p了大量时_加上在VS2005调试q程中,有个别文件更新时没有被重新编译,也耗费了很多无谓的旉Q以至于我们都在考虑是不是要攑ּIDEQ因为我们确实太依赖IDE了,有些TXZE_Q每ơ都是“重新生成整个解x案”,如果一个解x案有几千个文件、几十万行的代码Q估计重~一ơ也要花个几分钟吧?

ȝQ?/strong>

  1. netstat观察的网l连接处于ESTABLISHED状态ƈ不意味着逻辑q接被acceptQ只是表明客Lconnect的TCP物理q接Q三ơ握手)被服务器端ackQ如果服务器没有accept到该q接Q证明网l模块代码有问题Q?
  2. 多线E怎么都是个问题,U程同步量避免Q毕竟,用Kevin的话来说Q加锁是丑陋的。但在涉及到同步问题Ӟq是权衡一下,我这儿之所以最后没有加临界区,是因Z件主要是在ThreadA中处理,ThreadB中只有create操作Q而且ThreadA对事仉的刷新要求不是那么严|也就不考虑加界区了;
  3. 如果能力和条件允许的话,攑ּIDE吧,IDE的确不是个好东西Q我主要是指在编译链接的时候,如果作ؓ~辑器说不定q会好用:)?

个h|站用的L最q从据说要黑屏的Windows换成了DebianQ还在调_估计明天能弄好,内容肯定比Cppblog杂的多,谈点技术的q是会同步更新到?/p>

Fox 2008-10-27 23:25 发表评论
]]>
支持成员函数指针的消息映机制的单实?/title><link>http://www.shnenglu.com/Fox/archive/2008/10/10/63625.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Fri, 10 Oct 2008 02:20:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/10/10/63625.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/63625.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/10/10/63625.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/63625.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/63625.html</trackback:ping><description><![CDATA[<p>作者:Fox</p> <p>本文同时发布?a >http://www.yulefox.com</a>?a href="http://www.shnenglu.com/fox">http://www.shnenglu.com/fox</a>?/p> <p>十天之前Q在CPPBLOG上写了一?a title="消息映射机制的简单实? href="http://www.shnenglu.com/Fox/archive/2008/09/29/63056.html" target="_blank" rel="tag">消息映射机制的简单实?/a>Q有同学提到该实C支持成员函数。这个问题我也考虑CQ既然被提出来,不妨把实现提供出来?/p> <p>需要说明的是,我本w对template比较不感冒,不过<a title="Kevin Lynx" href="http://www.shnenglu.com/kevinlynx/archive/2008/03/17/44678.html" target="_blank" rel="tag">Kevin Lynx</a>对template感冒Q而且写过关于成员函数指针的问题,想了很久Q如果支持成员函数指针,不用模板是不行了?/p> <p>此处Ҏ员函数的支持q不涉及对函数参数的泛化Q因为我q个消息映射暂时不需要参数泛化,下面的代码应该不需要过多的解释了?/p><code> <p>#define REG_MSG_FUNC(nMsgType, MsgFunc) \ <br>    CMsgRegister::RegisterCallFunc(nMsgType, MsgFunc); </p> <p>#define REG_MSG_MEM_FUNC(nMsgType, Obj, MsgFunc) \ <br>    CMsgRegister::RegisterCallFunc(nMsgType, Obj, MsgFunc); </p> <p>class CBaseMessage; </p> <p>class CHandler <br>{ <br>public: <br>    virtual int operator()(CBaseMessage* pMsg) = 0; <br>}; </p> <p>template<typename FuncType> <br>class CDefHandler : public CHandler <br>{ <br>public: <br>    CDefHandler(){} <br>    CDefHandler(FuncType &Func) <br>        : m_Func(Func) <br>    { <br>    } </p> <p>    virtual int operator()(CBaseMessage* pMsg) <br>    { <br>        return m_Func(pMsg); <br>    } </p> <p>protected: <br>    FuncType    m_Func; <br>}; </p> <p>template<typename ObjType, typename FuncType> <br>class CMemHandler : public CHandler <br>{ <br>public: <br>    CMemHandler(){} <br>    CMemHandler(ObjType* pObj, FuncType Func) <br>        : m_pObj(pObj) <br>        , m_Func(Func) <br>    { <br>    } </p> <p>    virtual int operator()(CBaseMessage* pMsg) <br>    { <br>        return (m_pObj->*m_Func)(pMsg); <br>    } </p> <p>protected: <br>    FuncType    m_Func; <br>    ObjType*    m_pObj; <br>}; </p> <p>class CFunction <br>{ <br>public: <br>    CFunction() <br>        : m_pHandler(NULL) <br>    { <br>    } </p> <p>    // 装(C函数或静态成员函? <br>    template<typename FuncType> <br>    CFunction( FuncType &Func ) <br>        : m_pHandler(new CDefHandler<FuncType>(Func)) <br>    { <br>    } </p> <p>    // 装(非静态成员函? <br>    template<typename ObjType, typename FuncType> <br>    CFunction( ObjType* pObj, FuncType Func ) <br>        : m_pHandler(new CMemHandler<ObjType, FuncType>(pObj, Func)) <br>    { <br>    } </p> <p>    virtual ~CFunction() <br>    { <br>        DELETE_SAFE(m_pHandler); <br>    } </p> <p>        // 函数调用 <br>    int operator()(CBaseMessage* pMsg) <br>    { <br>        return (*m_pHandler)(pMsg); <br>    } </p> <p>private: <br>    CHandler    *m_pHandler; <br>}; </p> <p>typedef std::map<int, CFunction*> MSG_MAP; <br>typedef MSG_MAP::iterator MSG_ITR; </p> <p>class CMsgRegister <br>{ <br>public: <br>    // 注册消息函数(C函数或静态成员函? <br>    template <typename FuncType> <br>    inline static void RegisterCallFunc(int nMsgType, FuncType &Func) <br>    { <br>        CFunction *func = new CFunction(Func); <br>        s_MsgMap[nMsgType] = func; <br>    } </p> <p>    // 注册消息函数(非静态成员函? <br>    template <typename ObjType, typename FuncType> <br>    inline static void RegisterCallFunc(int nMsgType, ObjType* pObj, FuncType Func) <br>    { <br>        CFunction *func = new CFunction(pObj, Func); <br>        s_MsgMap[nMsgType] = func; <br>    } </p> <p>    // 执行消息 <br>    inline static void RunCallFunc(int nMsgType, CBaseMessage* pMsg) <br>    { <br>        MSG_ITR itr = s_MsgMap.find(nMsgType); <br>        if( s_MsgMap.end() != itr ) <br>        { <br>            (*itr->second)(pMsg); <br>        } <br>    } </p> <p>    static void ReleaseMsgMap()                // 释放消息映射?<br>    { <br>        MSG_ITR itr = s_MsgMap.begin(); <br>        while( itr != s_MsgMap.end() ) <br>        { <br>            DELETE_SAFE(itr->second); <br>            itr = s_MsgMap.erase(itr); <br>        } <br>    } </p> <p>protected: <br>    static MSG_MAP            s_MsgMap;        // 消息映射?<br>};</p></code> <p>不可否认Q模板给了你更大的想象空_很多东西Q还是不要一x斥的?)?/p><img src ="http://www.shnenglu.com/Fox/aggbug/63625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-10-10 10:20 <a href="http://www.shnenglu.com/Fox/archive/2008/10/10/63625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>消息映射机制的简单实?/title><link>http://www.shnenglu.com/Fox/archive/2008/09/29/63056.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Mon, 29 Sep 2008 10:34:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/09/29/63056.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/63056.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/09/29/63056.html#Feedback</comments><slash:comments>19</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/63056.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/63056.html</trackback:ping><description><![CDATA[<p>目中用了消息通信机制Q因为消息类型非常多Q相应的Q处理消息的地方代码也非常多? <p>自然而然惛_MFC中的消息映射Q? <p>创徏一个缺省MFC框架E序的解x案TestQ在Test.h中看C下内容: <code> <p>class Ctest_mfcApp : public CWinApp<br>{<br>public:<br>    Ctest_mfcApp(); <p>// 重写<br>public:<br>    virtual BOOL InitInstance(); <p>// 实现<br>    afx_msg void OnAppAbout();<br>    DECLARE_MESSAGE_MAP()<br>}; <p> </code></p> <p>其中Q最紧要的就?code>DECLARE_MESSAGE_MAP()</code>q个宏,相关内容展开如下Q?<code> <p>struct AFX_MSGMAP_ENTRY<br>{<br>    UINT nMessage;   // windows message<br>    UINT nCode;      // control code or WM_NOTIFY code<br>    UINT nID;        // control ID (or 0 for windows messages)<br>    UINT nLastID;    // used for entries specifying a range of control id's<br>    UINT_PTR nSig;   // signature type (action) or pointer to message #<br>    AFX_PMSG pfn;    // routine to call (or special value)<br>}; <p>struct AFX_MSGMAP<br>{<br>    const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();<br>    const AFX_MSGMAP_ENTRY* lpEntries;<br>}; <p>#define DECLARE_MESSAGE_MAP() \<br>protected: \<br>    static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \<br>    virtual const AFX_MSGMAP* GetMessageMap() const; \</code> <p>其中<code>AFX_PMSG</code>不再解析下去Q我们认是一个指向特定消息对应的实现函数的函数指针,q几个宏的作用可单理解成为Testq个目定义了一个静态的消息映射表。当消息到来Ӟ从消息队列中弹出消息q分发到h入口实现的上层CWndzH口。用户只需要注册消息,实现消息入口函数够了,q在MFC中一般放?cpp文g头部。Test.cpp中头部有以下内容Q?<code> <p>BEGIN_MESSAGE_MAP(CTest, CWinApp)<br>    ON_COMMAND(ID_APP_ABOUT, &CTest::OnAppAbout)<br>    // Z文g的标准文档命?br>    ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)<br>    ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)<br>    // 标准打印讄命o<br>    ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)<br>END_MESSAGE_MAP()</code> <p>q里是ؓ消息枚Dg消息实现函数建立映射Q其中涉及到的宏的展开如下Q?/p><code> <p>#define ON_COMMAND(id, memberFxn) \<br>    { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \<br>        static_cast<AFX_PMSG> (memberFxn) }, <p>#define BEGIN_MESSAGE_MAP(theClass, baseClass) \<br>    PTM_WARNING_DISABLE \<br>    const AFX_MSGMAP* theClass::GetMessageMap() const \<br>        { return GetThisMessageMap(); } \<br>    const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \<br>    { \<br>        typedef theClass ThisClass;                           \<br>        typedef baseClass TheBaseClass;                       \<br>        static const AFX_MSGMAP_ENTRY _messageEntries[] =  \<br>        { <p>#define END_MESSAGE_MAP() \<br>        {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \<br>    }; \<br>        static const AFX_MSGMAP messageMap = \<br>        { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \<br>        return &messageMap; \<br>    }                                  \<br>    PTM_WARNING_RESTORE <p></code>按照上述思\得到的相g码如下:</p><code> <p>// Test.h<br>typedef void (* funCall)(void*);        // 消息执行函数cd <p>struct tagMsgEntry                      // 消息入口l构<br>{<br>    int            nMsgType;            // 消息cd<br>    funCall        MsgRun;              // 消息执行函数<br>}; <p>struct tagMsgMap                        // 消息映射表结?br>{<br>    const tagMsgMap* (__stdcall* funGetBaseMsgMap)();<br>    const tagMsgEntry* pMsgEntries;     // 消息入口?br>}; <p>class CMessage<br>{<br>    // ...<br>protected:<br>    static const tagMsgMap* __stdcall GetThisMsgMap();<br>    virtual const tagMsgMap* GetMsgMap() const;<br>}; <p>// Test.cpp<br>const tagMsgMap* CMessage::GetMsgMap() const<br>{<br>    return GetThisMsgMap();<br>} <p>const tagMsgMap* __stdcall CMessage::GetThisMsgMap()<br>{<br>    static const tagMsgEntry MsgEntries[] =<br>    {<br>        { MSG_SOME_ONE, SomeOneFunc },<br>        { MSG_SOME_TWO, SomeTwoFunc },<br>        { MSG_NULL, NULL }<br>    };<br>    static const tagMsgMap msgMap =<br>    {<br>        &CBaseMessage::GetThisMsgMap,    // 父类消息映射?br>        &MsgEntries[0]<br>    };<br>    return &msgMap;<br>} </p> <p>int CMessage::MsgProc(int nMsgType)<br>{<br>    switch( nMsgType )<br>    {<br>    case MSG_SOME_ONE:<br>        { <p>        }<br>        break;<br>    }<br>    return CBaseMessage::MsgProc(nMsgType);<br>}</code> <p>q种处理的优点在于,子类没有定义的消息实现接口,可以使用父类接口实现。不q在现在的消息处理中Q我们一般不需要由基类来完成,因此可以不依赖基cL口,使用宏可以代码看上L加简z? <p>___________________________________________________________ <p>化版本的消息映射采用以下方式Q简单清晎ͼ<code> <p>// Test.h<br>#define REG_MSG_FUNC(nMsgType, MsgFunc) \<br>    CMessge::RegisterCallFunc(nMsgType, MsgFunc); \ <p>typedef void (* function)(void*); <p>typedef std::map<int, function> MSG_MAP;<br>typedef MSG_MAP::const_iterator MSG_CITR; <p>class CMessage<br>{<br>    // ...<br>public:<br>    static const MSG_MAP& GetMsgMap();<br>    static void RegisterCallFunc(int nMsgType, void(* Func)(void *))<br>    {<br>        s_MsgMap[nMsgType] = Func;<br>    } <p>    int CMessage::Run(int nMsgType)                // 消息公用执行函数<br>    {<br>        MSG_ITR itr = s_MsgMap.find(nMsgType);<br>        if( s_MsgMap.end() != itr )<br>        {<br>            itr->second(this);<br>        }<br>    } <p>protected:<br>    static MSG_MAP            s_MsgMap;            // 消息映射?br>}; <p>// UserTest.cpp -- 用户在用时对自己关心的消息予以注册, 入口函数予以实现卛_<br>REG_MSG_FUNC(MSG_SOME_ONE, SomeOneFunc) <p>void SomeOneFunc(CBaseMessage *pMsg)<br>{<br>    return;<br>}</code> <p>___________________________________________________________ <p>最q忙的焦头烂额,正好写到消息Q稍微整理一下,提供些许借鉴?/p><img src ="http://www.shnenglu.com/Fox/aggbug/63056.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-09-29 18:34 <a href="http://www.shnenglu.com/Fox/archive/2008/09/29/63056.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再L同步/异步与阻?非阻?/title><link>http://www.shnenglu.com/Fox/archive/2008/09/11/61555.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Wed, 10 Sep 2008 17:11:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/09/11/61555.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/61555.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/09/11/61555.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/61555.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/61555.html</trackback:ping><description><![CDATA[<p>|络~程学习和实늚q程中,<strong>同步QsynchronousQ?异步QasynchronousQ?/strong>?strong>dQblockingQ?非阻塞(non-blockingQ?/strong>L会迷惑很多h。依然记得我半年之前?a title="MMORPG|络模型剖析——IOCP? href="http://www.shnenglu.com/Fox/archive/2008/03/06/mmorpg_net_iocp.html" target="_blank">记述IOCP</a>Ӟ一句不l意的?strong>非阻塞I/O则是致力于提供高效的异步I/O</strong>”便引来一番口水论争?/p> <p>今天在查一些资料的时候,看到关于q几个词的论辩竟不是一般的多,l细xQ这个问题似乎也实有解释的必要Q不在于争论寚wQ而在于L明是非?/p> <p>讨论之前Q先限定讨论的范_<strong>此处之同?异步仅限于I/O操作</strong>Q与OS所讨论的进E?U程中的<strong>其他同步/异步</strong>没有直接关系Q讨论的内容是:<strong>两对怼的术语之间的区别到底有多?/strong>?/p> <ul> <li><strong>非常大:</strong></li></ul> <p>Douglas C. Schmidt在《C++|络~程》中q样说到Q?/p> <p>They are very different, as follows:</p> <p>AIO is "asynchronous I/O", i.e., the operation is invoked asynchronously and control returns to the client while the OS kernel processes the I/O request.  When the operation completes there is some mechanism for the client to retrieve the results.</p> <p>Non-blocking I/O tries an operation (such as a read() or write()) and if it the operation would block (e.g., due to flow control on a TCP connection or due to lack of data in a socket), the call returns -1 and sets errno to EWOULDBLOCK.</p> <p>译如下Q?/p> <p><a title="异步I/O" target="_blank" rel="tag">异步I/O</a>Q例如,操作被异步调用时Q控制权交给客户端,I/O操作h则交由操作系l内核处理,当操作完成后Q通过某种机制结果通知客户端?/p> <p>非阻塞I/OQ尝试调用某操作Q如果操作被dQ则调用q回-1q置错误gؓEWOULDBLOCK?/p> <p>从这两段“very different”的解释来看Q我的感觉是q没有指Z者的区别Q因为我们无法确定所谓AIO是如何处理的Q如果AIO直接“调用返?1q置错误gؓEWOULDBLOCK”,实现“控制权交给客户端”,gq无M不妥。况且,对于非阻塞I/OQ我们也需要“当操作完成后,通过某种机制结果通知客户端”这L处理?/p> <ul> <li><strong>无差别:</strong></li></ul> <p>而在<a title="Wikipedia" target="_blank">Wikipedia</a>上则直接{同二者:<b>Asynchronous I/O</b>, or <b>non-blocking I/O</b>, is a form of <a title="I/O" target="_blank">input/output</a> processing that permits other processing to continue before the transmission has finished.</p> <p>当然Q对于recv和sendQ我们一般会说他们是<strong>d</strong>LQ而不会说他们?strong>同步</strong>LQ但q显然不是二者的区别Q因为我们都知道Q?strong>d的原因正是等待同步结果的q回</strong>?/p> <p>因此Q二者的区别在于Q?strong>d/非阻塞是表现Q同?异步是原?/strong>Q我们说某某操作是阻塞v的,或者某某线E是dLQ是因ؓ在等待操作结果的同步q回Q我们说某某操作是非d的,是因为操作结果会通过异步方式q回?/p> <p>讨论到这儿,再咬文嚼字的争辩下去g已经没有M实际意义?/p> <p>------------------------------------------------------------</p> <p>PSQ纠l一些必要的概念是ؓ了加q解,太过U结了反倒会滞塞理解。我之前对于其概念也q特别清楚Q所以才会再l一特意言明,也算弥补一下自qq失?/p><img src ="http://www.shnenglu.com/Fox/aggbug/61555.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-09-11 01:11 <a href="http://www.shnenglu.com/Fox/archive/2008/09/11/61555.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式Q一Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/08/06/58154.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Wed, 06 Aug 2008 07:43:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/08/06/58154.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/58154.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/08/06/58154.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/58154.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/58154.html</trackback:ping><description><![CDATA[<p><strong><font color=#800000>0. Introduction</font></strong></p> <p>接触设计模式有两q时间了Q但一直没有系l整理过Qؓ了不至于让自q思维被繁琐的工作一点点锢Q还是决定ȝ一下,Z能够真正做到有所收获Q整个系列会按照<a title="Gang of Four" target=_blank>GoF的Design Patterns: Elements of Reusable Object-Oriented Software</a>的行文思\Q但不会照本宣科是了,<a title=Wikipedia target=_blank>Wikipedia</a>上关?3U设计模式的介绍非常全面QCSDN上也可以下蝲?英文电子档,因此很多套话、类图一概省厅R?/p> <p>最早接触设计模式的时候,隑օ被各U模式的联系和区别所困扰Q从教科书的分析可以得到模式之间形式上的不同。但q样对于领会设计模式意义不大Q因为我们掌握模式的目的是ؓ了融会诏通,灉|q用Q以对开发有所帮助?/p> <p>E微成规模的OOE序Q会有大量对象,其中很多实体对象之间存在着<strong>父子、兄?/strong>关系Q对象的<strong>创徏</strong>提升ZU模式。其好处在于设计模式本n所宣称?strong>reusable</strong>Q这像堆积木盖房子一P堆的好的情况下,换一换门H便是另一番风景?/p> <p>关于实现Q我不会Z厘清模式间的区别而刻意用相g码实玎ͼ相反Q我会根据模式本w的适用情况举例Q而且大量代码Z<a title=http://sourcemaking.com/design_patterns target=_blank>SourceMaking</a>?/p> <p>_______________________________</p> <p><strong><font color=#800000>1. Creational Design Patterns(DP)</font></strong></p> <p>创徏型DP抽象了类和对象的创徏q程Q?a title="Gang of Four" target=_blank>GoF</a>l出?U?strong>创徏型DP</strong>Q?strong>Abstract Factory</strong>?strong>Builder</strong>?strong>Factory Method</strong>?strong>Builder</strong>?strong>Prototype</strong>?strong>Singleton</strong>?/p> <p><strong><font color=#800000>2. Abstract Factory</font></strong></p> <p><strong>意图Q提供一个创Zpd相关或相互依赖对象的接口Q而无需指定它们具体的类?/strong></p> <p>1) 只提供了一个创建接口,其返回gؓ具体产品Q如<code>AbstractProduct *Client::CreateProduct(AbstractFactory &factory);</code></p> <p>2) 接口的参数是一?strong>工厂对象</strong>Q?code>AbstractFactory &factory</code>Q的引用Q参数类型(<code>AbstractFactory</code>Qؓ抽象基类Q调用时Ҏ需要传入具体工厂对象即可;</p> <p>3) 接口内部实现?strong>一pd相关或相互依赖对?/strong>Q抽象品)的创建:当传入具体工厂时Q接口实现的是<strong>一pd具体产品</strong>的创建;</p> <p>4) 创徏的?strong>立即q回</strong>Q?code>CreateProduct</code>Q?/p> <p><strong>参与者:</strong></p> <p>• AbstractFactory<br>?声明一个创建抽象品对象的操作接口?/p> <p>• ConcreteFactory<br>?实现创徏具体产品对象的操作?/p> <p>• AbstractProduct<br>?ZcM品对象声明一个接口?/p> <p>• ConcreteProduct<br>?定义一个将被相应的具体工厂创徏的品对象?br>?实现AbstractProduct接口?/p> <p>• Client<br>?仅用由AbstractFactory和AbstractProductcd明的接口?/p> <p><strong>代码Q?/strong></p> <code> <p>class AbstractFactory<br>{<br>public:<br>    virtual AbstractProduct *MakePartA() = 0;<br>    virtual AbstractProduct *MakePartB() = 0;<br>    virtual AbstractProduct *MakePartC() = 0;<br>    virtual AbstractProduct *AddPart(const AbstractProduct *pPart) = 0;<br>}; <p>AbstractProduct *Client::CreateProduct(AbstractFactory &factory)<br>{<br>    AbstractProduct *pProduct = factory.CreateProduct();<br>    AbstractProduct *pPartA = factory.MakePartA();<br>    AbstractProduct *pPartB = factory.MakePartB();<br>    AbstractProduct *pPartC = factory.MakePartC();<br>    factory.AddPart(pPartA);<br>    factory.AddPart(pPartB);<br>    factory.AddPart(pPartC);<br>    return pProduct;<br>} </p> <p>int main(void)<br>{<br>    Client client;            <br>    ConcreteFactory factory;<br>    client.CreateProduct(factory);<br>    return 0;<br>}</code> <p><strong><font color=#800000>3. Builder</font></strong></p> <p><strong>意图Q将一个复杂对象的构徏与它的表C分,使得同样的构E可以创Z同的表示?/strong></p> <p>1) director提供抽象产品创徏接口Q如<code>void Director::Construct();</code></p> <p>2) 不同产品使用<strong>同一创徏q程</strong>Q由director指定特定builder以生产不同品;</p> <p>3) 接口内部实现?strong>一个复杂对?/strong>Q抽象品)的创建:当传入具体工厂时Q接口实现的?strong>一个复杂的具体产品</strong>的创建;</p> <p>4) 创徏的?strong>q不立即q回</strong>Q?strong>创徏完毕</strong>后返回,?strong>使用接口</strong>Q?code>GetProduct</code>Q提取结果?/p> <p><strong>参与者:</strong></p> <p>• Builder<br>?为创Z个Product对象的各个部件指定抽象接口?/p> <p>• ConcreteBuilder<br>?实现Builder的接口以构造和装配该品的各个部g?br>?定义q明它所创徏的表C?br>?提供一个检索品的接口?/p> <p>• Director<br>?构造一个用Builder接口的对象?/p> <p>• Product<br>?表示被构造的复杂对象。ConcreteBuilder创徏该品的内部表示q定义它的装配过E?br>?包含定义l成部g的类Q包括将q些部g装配成最l品的接口?/p> <p><strong>代码Q?/strong></p> <code> <p>class Builder<br>{<br>public:<br>    virtual void MakePartA() = 0;<br>    virtual void MakePartB() = 0;<br>    virtual void MakePartC() = 0; <p>    Product *GetProduct()    { return _product; } <p>protected:<br>    Product *_product;<br>}; <p>class Director<br>{<br>public:<br>    void setBuilder(Builder *b)    { _builder = b; }<br>    void Construct(); <p>private:<br>    Builder *_builder;<br>}; <p>void Director::Construct()<br>{<br>    _builder.MakePartA();<br>    _builder.MakePartB();<br>    _builder.MakePartC();<br>} <p>int main(void) {<br>    ConcreteBuilderA concreteBuilderA;<br>    ConcreteBuilderB concreteBuilderB;<br>    Director director;<br>    Product *pProduct; <p>    director.SetBuilder(&concreteBuilderA);<br>    director.Construct();<br>    pProduct = concreteBuilderA.GetProduct();<br>    pProduct->Show(); <p>    director.SetBuilder(&concreteBuilderB);<br>    director.Construct();<br>    pProduct = concreteBuilderB.GetProduct();<br>    pProduct->Show(); <p>    return 0;<br></code>}</p> <p><strong><font color=#800000>4. Factory Method</font></strong></p> <p><strong>意图Q定义一个用于创建对象的接口Q让子类军_实例化哪一个类。Factory Method使一个类的实例化延迟到其子类?/strong></p> <p>1) 看得模式其实是<strong>C++的多态特?/strong>Q?strong>l承</strong>实现。因此,其别名ؓ<strong>虚构造器Q?Virtual ConstructorQ?/strong>Q?/p> <p>2) 作ؓ模式与C++多态特性不同的是,Creator可以定义<strong>工厂Ҏ的缺省实?/strong>Q完成缺省操作,MFC大量使用了这一思想?/p> <p><strong>参与者:</strong></p> <p>• Product<br>?定义工厂Ҏ所创徏的对象的接口?/p> <p>• ConcreteProduct<br>?实现Product接口?/p> <p>• Creator<br>?声明工厂ҎQ该Ҏq回一个Productcd的对象。Creator也可以定义一个工厂方法的~省实现Q它q回一个缺省的ConcreteProduct对象?br>?可以调用工厂Ҏ以创Z个Product对象?/p> <p>• ConcreteCreator<br>?重定义工厂方法以q回一个ConcreteProduct实例?/p> <p><strong>代码Q?/strong></p> <p><code>ConcreteProduct *ConcreteCreator::FactoryMethod()<br>{<br>    <code>ConcreteProduct</code> *pProduct = new <code>ConcreteProduct</code>;<br>    return pProduct;<br>}</code></p> <p><code>Product *Creator::FactoryMethod()<br>{<br>    Product *pProduct = new Product;<br>    return pProduct;<br>} </p> <p>int main(void) {<br>    Creator creator;<br>    ConcreteProduct *pProduct; <p>    pProduct = creator.FactoryMethod();<br>    pProduct->Show(); <p>    return 0;<br>}</code> <p><strong><font color=#800000>5. Prototype</font></strong></p> <p><strong>意图Q用原型实例指定创徏对象的种c,q且通过拯q些原型创徏新的对象?/strong></p> <p>1) 创徏不再通过工厂新类<strong>l承QinheritanceQ?/strong>Q而是通过<strong>委托QdelegationQ?/strong>Q?/p> <p>2) 栚w?strong>拯原型实例</strong>创徏新对象?/p> <p><strong>参与者:</strong></p> <p>• ProtoType<br>?声明一个克隆自w的接口?/p> <p>• ConcreteProtoType<br>?实现一个克隆自w的操作?/p> <p>• Client<br>?让一个原型克隆自w从而创Z个新的对象?/p> <p><strong>代码Q?/strong></p> <code> <p>class ProtoType<br>{<br>public:<br>    virtual void Draw();<br>    virtual ProtoType *Clone() = 0;<br>    virtual void Initialize();<br>}; <p>class ProtoTypeA: public ProtoType<br>{<br>public:<br>    virtual ProtoType *Clone()<br>    {<br>        return new ProtoTypeA;<br>    }<br>}; <p>class ProtoTypeB: public ProtoType<br>{ <br>public:<br>    virtual ProtoType *Clone()<br>    {<br>        return new ProtoTypeB;<br>    }<br>}; <p>class Client<br>{<br>public:<br>    static ProtoType *Clone( int choice ); <p>private:<br>    static ProtoType *s_prototypes[3];<br>}; <p>ProtoType* Client::s_prototypes[] = { 0, new ProtoTypeA, new ProtoTypeB }; <p>ProtoType *Client::Clone(int choice)<br>{<br>    return s_prototypes[choice]->Clone();<br>}</code> <p> </p> <p><strong><font color=#800000>6. Singleton</font></strong></p> <p><strong>意图Q保证一个类仅有一个实例,q提供一个访问它的全局讉K炏V?/strong></p> <p>1) ?strong>静态成员函?/strong>保证上述意图?/p> <p><strong>参与者:</strong></p> <p>• Singleton<br>?定义一个Instance操作Q允许客戯问它的唯一实例。Instance是一个类操作Q即C++中的一个静态成员函敎ͼ?br>?可能负责创徏它自q唯一实例?/p> <p> </p> <p><strong>代码Q?/strong></p> <code> <p>class Singleton<br>{<br>public:<br>    static Singleton *GetInstance()<br>    {<br>        if (!s_instance)<br>            s_instance = new Singleton;<br>        return s_instance;<br>    } <p>    void Run()    {} <p>private:<br>    static Singleton *s_instance;<br>    Singleton()    {}                // Singleton cannot be created outside.<br>}; <p>Singleton *GetSingleton(void)<br>{<br>    return Singleton::GetInstance();<br>} <p>int main(void)<br>{<br>    GetSingleton()->Run(); <p>    return 0;<br>}</p> </code> <p>______________________________________________</p> <p>代码写的都比较简单,基本可以各U模式之间的不同体现出来了?/p><img src ="http://www.shnenglu.com/Fox/aggbug/58154.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-08-06 15:43 <a href="http://www.shnenglu.com/Fox/archive/2008/08/06/58154.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Big-endian记忆Q附闲扯Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/07/30/57508.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Wed, 30 Jul 2008 06:48:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/07/30/57508.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/57508.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/07/30/57508.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/57508.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/57508.html</trackback:ping><description><![CDATA[<p><strong><font color="#800000">一、Big-endian & Little-endian</font></strong></p> <p>q是<a title="Wikipedia" target="_blank">Wikipedia</a>好啊Q可惜中文的国内看不了,愚昧啊!实在觉得中文有点难懂Q看?a title="Wikipedia 日本语版? target="_blank">日本语版?/a>?DQ?/p> <p>关于<strong>端(endiannessQ?/strong>的介l,<a title="Wikipedia" target="_blank">Wikipedia</a>上比较全了:<a title="http://en.wikipedia.org/wiki/Endianness" >http://en.wikipedia.org/wiki/Endianness</a></p> <p>关于<strong>|络字节序(network byte orderQ?/strong>?strong>L字节序(host byte orderQ?/strong>Q说来挺无关紧要的一点东西,因ؓ每次L忘掉Q所以每ơ都要好奇的看看<strong>大端Qbig-endianQ?/strong>?strong>端Qlittle-endianQ?/strong>?/p> <p>l定<code>unsigned long</code>型整数十六进制Ş式:<tt>0x0A0B0C0D</tt>Q其big-endian和little-endian形式分别为:</p> <p><strong>1) Big-endian</strong></p> <p><tt>Memory<br>| </tt><tt>...  |  8-bit atomic element size       </tt><tt>| </tt><tt>...    |  16-bit atomic element size</tt><br><tt>| </tt><tt>0x0A |  a                               <tt>| </tt><tt>0x0A0B |  a<br></tt></tt><tt>| </tt><tt>0x0B |  a+1                             <tt>| </tt><tt>0x0C0D |  a+</tt>1</tt><br><tt>| </tt><tt>0x0C |  a+2<br></tt><tt>| 0x0D |  a+3<br></tt><tt>| ...  |</tt></p> <p><strong>2) Little-endianQX86Q?/strong></p> <p><tt>Memory<br>| </tt><tt>...  |  8-bit atomic element size       </tt><tt>| </tt><tt>...    |  16-bit atomic element size</tt><br><tt>| </tt><tt>0x0D |  a                               <tt>| </tt><tt>0x0C0D |  a<br></tt></tt><tt>| </tt><tt>0x0C |  a+1                             <tt>| </tt><tt>0x0A0B |  a+</tt>1</tt><br><tt>| </tt><tt>0x0B |  a+2<br></tt><tt>| 0x0A |  a+3<br></tt><tt>| ...  |</tt></p> <p align="center"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Endianessmap.svg/250px-Endianessmap.svg.png"> </p> <p align="center">Mapping registers to memory locations (from Wikipedia)</p> <p>Z么X86存储会用little-endianQv初我惛_于位q算Q尤其是位移q算Qlittle-endian很方便,但{念一惻Ibig-endian也方便啊Q无非是左移和右Uȝ区别而已Q但little-endian的优势在于unsigned char/short/int/longcd转换Ӟ存储位置无需改变?/p> <p>在网l传输中Q采用big-endian序,对于<tt>0x0A0B0C0D</tt>Q传输顺序就?tt>0A 0B 0C 0D</tt>Q因此big-endian作ؓnetwork byte orderQlittle-endian作ؓhost byte order?/p> <p>________________________________________________</p> <p><strong>PSQ做鸡有什么不好?</strong></p> <p>上午跟某同事Qؓ重虑,下文以YUCQ躲在犄角旮旯抽烟。以下ؓ场景再现Q?/p> <p>Q忽然整出来一句)YQ听q鹰的故事没有?</p> <p>Q满脸疑惑)FoxQ没有?/p> <p>YQ一只小鹰掉到鸡H里Q?$@%…?/p> <p>FQ我不是鹎ͼ我就是一只鸡Q做<strike>技?/strike>鸡有什么不好?</p> <p>YQ做技术没有不好啊…?/p> <p>FQ我不是说做技术,我说做鸡Q我是在地上走的,我ؓ什么L要抬头看天?</p> <p>YQ你要往上看Q没有h注定不能飞,XX以前也没有想q有一天会飞v来?/p> <p>FQ我不是掉到鸡窝里,我本来就在鸡H里Q我也喜Ƣ呆在鸡H里Q别人都在地上走Q我Z么要飞v来?</p> <p>YQ你总要飞v来?/p> <p>FQ我说了我喜Ƣ呆在鸡H里Q你见过有那只鸡飞v来了Q?/p> <p>YQ…?/p> <p>FQ我是一只鸡Q插了鸡还是飞不v来,况且Q我寚wh也没有Q何兴?/p> <p>YQ…?/p> <p>FQ做鸡有什么不好?</p> <p>YQ你看老毛Q与人斗其乐无穷Q他境界多高Q与天斗其乐无穷Q知道吧Q他已经不屑与h斗了?/p> <p>FQ我不喜Ƣ与人斗Q我也斗不过Q做鸡有什么不好?</p> <p>YQ…?/p><img src ="http://www.shnenglu.com/Fox/aggbug/57508.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-07-30 14:48 <a href="http://www.shnenglu.com/Fox/archive/2008/07/30/57508.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[译]Google C++~程风格指南Q八Q[完]http://www.shnenglu.com/Fox/archive/2008/07/23/56933.htmlFoxFoxWed, 23 Jul 2008 06:28:00 GMThttp://www.shnenglu.com/Fox/archive/2008/07/23/56933.htmlhttp://www.shnenglu.com/Fox/comments/56933.htmlhttp://www.shnenglu.com/Fox/archive/2008/07/23/56933.html#Feedback11http://www.shnenglu.com/Fox/comments/commentRss/56933.htmlhttp://www.shnenglu.com/Fox/services/trackbacks/56933.html原文地址Q?a title="Google C++ Style Guide" target="_blank" rel="tag">Google C++ Style Guide
  • 规则之例?/font>

前面说明的编码习惯基本是强制性的Q但所有优U的规则都允许例外?/p>

1. 现有不统一代码QExisting Non-conformant CodeQ?/font>

对于现有不符合既定编E风格的代码可以|开一面?/p>

当你修改使用其他风格的代码时Qؓ了与代码原有风格保持一致可以不使用本指南约定。如果不攑ֿ可以与代码原作者或现在的负责h员商讨,CQ一致性包括原有的一致性?/p>

1. Windows代码QWindows CodeQ?/font>

WindowsE序员有自己的编码习惯,主要源于Windows的一些头文g和其他Microsoft代码。我们希望Q何h都可以顺利读懂你的代码,所以针Ҏ有^台的C++~码l出一个单独的指导Ҏ?/p>

如果你一直用Windows~码风格的,q儿有必要重申一下某些你可能会忘记的指南Q译者注Q我怎么感觉像在被洗?DQ?/font>Q?/p>

1) 不要使用匈牙利命名法QHungarian notationQ如定义整型变量?code>iNumQ?/font>Q用Google命名U定Q包括对源文件?code>.cc扩展名;

2) Windows定义了很多原有内建类型的同义?font color="#800000">Q译者注Q这一点,我也很反感)Q如DWORD?code>HANDLE{等Q在调用Windows API时这是完全可以接受甚至鼓qQ但q是量使用原来的C++cdQ例如,使用const TCHAR *而不?code>LPCTSTRQ?/p>

3) 使用Microsoft Visual C++q行~译Ӟ?strong>警告U别讄?或更?/strong>Qƈ所有warnings当作errors处理Q?/p>

4) 不要使用#pragma once;作ؓ包含保护Q用C++标准包含保护Q?strong>包含保护的文件\径包含到目树顶?font color="#800000">Q译者注Q?code>#include<prj_name/public/tools.h>Q?/font>Q?/p>

5) 除非万不得已Q否则不使用M不标准的扩展Q如#pragma?code>__declspecQ允怋?code>__declspec(dllimport)?code>__declspec(dllexport)Q但必须通过DLLIMPORT?code>DLLEXPORT{宏Q以便其他h在共享用这些代码时Ҏ攑ּq些扩展?/p>

在Windows上,只有很少一些偶可以不遵守的规则:

1) 通常我们止使用多重l承Q但在?a title="Component Object Model (COM)" target="_blank">COM?a title="Active Template Library (ATL)" target="_blank">ATL/WTLcL可以使用多重l承Qؓ了执?a title="Component Object Model (COM)" target="_blank">COM?a title="Active Template Library (ATL)" target="_blank">ATL/WTLcd其接口时可以使用多重实现l承Q?/p>

2) 虽然代码中不应用异?/strong>Q但?a title="Active Template Library (ATL)" target="_blank">ATL和部?a title="Standard Template Library (STL)" target="_blank">STLQ包括Visual C++的STLQ中异常被广泛用,使用ATLӞ应定?code>_ATL_NO_EXCEPTIONS以屏蔽异常,你要研究一下是否也屏蔽掉STL的异常,如果不屏蔽,开启编译器异常也可以,注意q只是ؓ了编译STLQ自׃然不要写含异常处理的代码Q?/p>

3) 通常每个目的每个源文g中都包含一个名?code>StdAfx.h?code>precompile.h的头文g方便头文仉~译Qؓ了代码方便与其他项目共享,避免昑ּ包含此文Ӟprecompile.cc除外Q,使用~译器选项/FI以自动包含;

4) 通常名ؓresource.h、且只包含宏的资源头文gQ不必拘泥于此风格指南?/p>

  • 团队合作

参考常识,保持一?/strong>?/p>

~辑代码Ӟq旉看看目中的其他代码q确定其风格Q如果其他代?code>if语句中用空|那么你也要用。如果其中的注释用星P*Q围成一个盒子状Q你也这样做Q?/p>

/**********************************
* Some comments are here.
* There may be many lines.
**********************************/

~程风格指南的用要点在于提供一个公q~码规范Q所有h可以把精力集中在实现内容而不是表现Ş式上。我们给Z全局的风D范,但局部的风格也很重要Q如果你在一个文件中新加的代码和原有代码风格相去甚远的话Q这q坏了文g本n的整体美观也影响阅读Q所以要量避免?/p>

好了Q关于编码风格写的差不多了,代码本n才是更有的Q尽情n受吧Q?/p>

Benjy Weinberger
Craig Silverstein
Gregory Eitzmann
Mark Mentovai
Tashana Landray

______________________________________

译者:l于d了,前后历时两周Q整个过E中Q虽因工作关pd有懈怠,但ȝ不是虎头蛇尾Qv码我的态度是非常认真的:DQ,无论是否能对你有所裨益Q对我而言Q至是温习了一些以前知道的知识Q也学到了一些之前不知道的知?/strong>?/strong>

刚好q两天还不是特紧张,赶紧d了,要开始干zM…?/strong>

Fox 2008-07-23 14:28 发表评论
]]>[译]Google C++~程风格指南Q七Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/07/23/56922.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Wed, 23 Jul 2008 03:43:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/07/23/56922.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/56922.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/07/23/56922.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/56922.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/56922.html</trackback:ping><description><![CDATA[<p>原文地址Q?a title="Google C++ Style Guide" target="_blank" rel="tag">Google C++ Style Guide</a></p> <ul> <li><strong><font color="#800000">格式</font></strong></li></ul> <p>代码风格和格式确实比较随意,但一个项目中所有h遵@同一风格是非常容易的Q作Z人未必同意下q格式规则的每一处,但整个项目服从统一的编E风格是很重要的Q这样做才能让所有h在阅d理解代码时更加容易?/p> <p><strong><font color="#800000">1. 行长度(Line LengthQ?/font></strong></p> <p>每一行代码字W数不超q?0?/p> <p>我们也认识到q条规则是存有争议的Q但如此多的代码都遵照这一规则Q我们感觉一致性更重要?/p> <p><strong>优点</strong>Q提倡该原则的h认ؓ他们调整~辑器窗口大很野蛮。很多h同时q排开几个H口Q根本没有多余空间拓宽某个窗口,Z窗口最大尺寸加以限定,一致?0列宽Qؓ什么要改变呢?</p> <p><strong>~点</strong>Q反对该原则的h则认为更宽的代码行更易阅读,80列的限制是上个世U?0q代的大型机的古板缺PC讑֤h更宽的显C屏Q很L的可以显C更多代码?/p> <p><strong>l论</strong>Q?0个字W是最大倹{例外:</p> <p>1) 如果一行注释包含了过80字符的命令或URLQ出于复制粘贴的方便可以过80字符Q?/p> <p>2) 包含长\径的可以出80列,量避免Q?/p> <p>3) 头文件保护(防止重复包含<a title="[译]Google C++~程风格指南Q一Q? href="http://www.shnenglu.com/Fox/archive/2008/07/10/55818.html" target="_blank">W一?/a>Q可以无视该原则?/p> <p><strong><font color="#800000">2. 非ASCII字符QNon-ASCII CharactersQ?/font></strong></p> <p>量不用非ASCII字符Q用时必须使用<a title="UTF-8" target="_blank">UTF-8</a>格式?/p> <p>哪怕是英文Q也不应用L面的文本编码到源代码中Q因此非ASCII字符要少用。特D情况下可以适当包含此类字符Q如Q代码分析外部数据文件时Q可以适当编码数据文件中作ؓ分隔W的非ASCII字符Ԍ更常用的是(不需要本地化的)单元试代码可能包含非ASCII字符丌Ӏ此cL况下Q应使用UTF-8格式Q因为很多工具都可以理解和处理其~码Q十六进制编码也可以Q尤其是在增强可L的情况下——如<code>"\xEF\xBB\xBF"</code>是Unicode?a title="zero-width no-break space" target="_blank">zero-width no-break space</a>字符Q以UTF-8格式包含在源文g中是不可见的?/p> <p><strong><font color="#800000">3. I格q是制表位(Spaces vs. TabsQ?/font></strong></p> <p>只用空|每次~进2个空根{?/p> <p>使用I格q行~进Q不要在代码中用tabsQ设定编辑器tab转ؓI格?/p> <p><strong>译者注Q在前段旉?/strong><a title="Debian开发学习日讎ͼ二)Q系l简单配|? href="http://www.shnenglu.com/Fox/archive/2008/06/06/debian_simple_configuration.html" target="_blank"><strong>关于Debian开发学习日?/strong></a><strong>一文中Q曾l出针对C/C++~码使用的vim配置?/strong></p> <p><strong><font color="#800000">4. 函数声明与定义(Function Declarations and DefinitionsQ?/font></strong></p> <p>q回cd和函数名在同一行,合适的话,参数也放在同一行?/p> <p>函数看上dq样Q?/p><pre>ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) { DoSomething(); ... } </pre> <p>如果同一行文本较多,容不下所有参敎ͼ</p><pre>ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2, Type par_name3) { DoSomething(); ... } </pre> <p>甚至q第一个参数都放不下:</p><pre>ReturnType LongClassName::ReallyReallyReallyLongFunctionName( Type par_name1, // 4 space indent Type par_name2, Type par_name3) { DoSomething(); // 2 space indent ... } </pre> <p>注意以下几点Q?/p> <p>1) q回值L和函数名在同一行;</p> <p>2) <font color="#800000">左圆括号Qopen parenthesisQ?/font>L和函数名在同一行;</p> <p>3) 函数名和左圆括号间没有空|</p> <p>4) 圆括号与参数间没有空|</p> <p>5) <font color="#800000">左大括号Qopen curly braceQ?/font>d最后一个参数同一行的末尾处;</p> <p>6) <font color="#800000">叛_括号Qclose curly braceQ?/font>L单独位于函数最后一行;</p> <p>7) <font color="#800000">叛_括号Qclose parenthesisQ?/font>和左大括号间L有一个空|</p> <p>8) 函数声明和实现处的所有Ş参名U必M持一_</p> <p>9) 所有Ş参应可能对齐;</p> <p>10) ~省~进?个空|</p> <p>11) 独立装的参C?个空格的~进?/p> <p>如果函数?code>const</code>的,关键?code>const</code>应与最后一个参C于同一行?/p><pre>// Everything in this function signature fits on a single line ReturnType FunctionName(Type par) const { ... } // This function signature requires multiple lines, but // the const keyword is on the line with the last parameter. ReturnType ReallyLongFunctionName(Type par1, Type par2) const { ... } </pre> <p>如果有些参数没有用到Q在函数定义处将参数名注释v来:</p><pre>// Always have named parameters in interfaces. class Shape { public: virtual void Rotate(double radians) = 0; } // Always have named parameters in the declaration. class Circle : public Shape { public: virtual void Rotate(double radians); } // Comment out unused named parameters in definitions. void Circle::Rotate(double /*radians*/) {}</pre><pre>// Bad - if someone wants to implement later, it's not clear what the // variable means. void Circle::Rotate(double) {} </pre> <p><strong>译者注Q关于UNIX/Linux风格Z么要把左大括L于行(.cc文g的函数实现处Q左大括号位于行首)Q我的理解是代码看上L较简U,x行首除了函数体被一对大括号在一起之外,只有叛_括号的代码看上去实也舒服;Windows风格左大括L于行首的优点是匹配情况一目了然?/strong></p> <p><strong><font color="#800000">5. 函数调用QFunction CallsQ?/font></strong></p> <p>量攑֜同一行,否则Q将实参装在圆括号中?/p> <p>函数调用遵@如下形式Q?/p><pre>bool retval = DoSomething(argument1, argument2, argument3); </pre> <p>如果同一行放不下Q可断ؓ多行Q后面每一行都和第一个实参对齐,左圆括号后和叛_括号前不要留I格Q?/p><pre>bool retval = DoSomething(averyveryveryverylongargument1, argument2, argument3); </pre> <p>如果函数参数比较多,可以Z可读性的考虑每行只放一个参敎ͼ</p><pre>bool retval = DoSomething(argument1, argument2, argument3, argument4); </pre> <p>如果函数名太长,以至于超q行最大长度,可以所有参数独立成行:</p><pre>if (...) { ... ... if (...) { DoSomethingThatRequiresALongFunctionName( very_long_argument1, // 4 space indent argument2, argument3, argument4); } </pre> <p><strong><font color="#800000">6. 条g语句QConditionalsQ?/font></strong></p> <p>更提倡不在圆括号中添加空|关键?code>else</code>另v一行?/p> <p>对基本条件语句有两种可以接受的格式,一U在圆括号和条g之间有空|一U没有?/p> <p>最常见的是没有I格的格式,那种都可以,q是<strong>一致?/strong>Z。如果你是在修改一个文Ӟ参考当前已有格式;如果是写新的代码Q参考目录下或项目中其他文g的格式,q在徘徊的话Q就不要加空g?/p><pre>if (condition) { // no spaces inside parentheses ... // 2 space indent. } else { // The else goes on the same line as the closing brace. ... } </pre> <p>如果你們֐于在圆括号内部加I格Q?/p><pre>if ( condition ) { // spaces inside parentheses - rare ... // 2 space indent. } else { // The else goes on the same line as the closing brace. ... } </pre> <p>注意所有情况下<code>if</code>和左圆括号间有个I格Q右圆括号和左大括号Q如果用的话)间也要有个空|</p><pre>if(condition) // Bad - space missing after IF. if (condition){ // Bad - space missing before {. if(condition){ // Doubly bad.</pre><pre>if (condition) { // Good - proper space after IF and before {. </pre> <p>有些条g语句写在同一行以增强可读性,只有当语句简单ƈ且没有?code>else子句</code>时用:</p><pre>if (x == kFoo) return new Foo(); if (x == kBar) return new Bar(); </pre> <p>如果语句?code>else</code>分支是不允许的:</p><pre>// Not allowed - IF statement on one line when there is an ELSE clause if (x) DoThis(); else DoThat(); </pre> <p>通常Q单行语句不需要用大括号Q如果你喜欢也无可厚非,也有?code>if</code>必须使用大括P</p><pre>if (condition) DoSomething(); // 2 space indent. if (condition) { DoSomething(); // 2 space indent. } </pre> <p>但如果语句中哪一分支使用了大括号的话Q其他部分也必须使用Q?/p><pre>// Not allowed - curly on IF but not ELSE if (condition) { foo; } else bar; // Not allowed - curly on ELSE but not IF if (condition) foo; else { bar; }</pre><pre> </pre><pre>// Curly braces around both IF and ELSE required because // one of the clauses used braces. if (condition) { foo; } else { bar; } </pre> <p><strong><font color="#800000">7. 循环和开关选择语句QLoops and Switch StatementsQ?/font></strong></p> <p><code>switch</code>语句可以使用大括号分块;I@环体应?code>{}</code>?code>continue</code>?/p> <p><code>switch</code>语句中的<code>case</code>块可以用大括号也可以不用,取决于你的喜好,使用时要依下文所q?/p> <p>如果有不满<code>case</code>枚D条g的|要L包含一?code>default</code>Q如果有输入值没?code>case</code>d理,~译器将报警Q。如?code>default</code>怸会执行,可以单的使用<code>assert</code>Q?/p><pre>switch (var) { case 0: { // 2 space indent ... // 4 space indent break; } case 1: { ... break; } default: { assert(false); } } </pre> <p>I@环体应?code>{}</code>?code>continue</code>Q而不是一个简单的分号Q?/p><pre>while (condition) { // Repeat test until it returns false. } for (int i = 0; i < kSomeNumber; ++i) {} // Good - empty body. while (condition) continue; // Good - continue indicates no logic.</pre><pre>while (condition); // Bad - looks like part of do/while loop. </pre> <p><strong><font color="#800000">8. 指针和引用表辑ּQPointers and Reference ExpressionsQ?/font></strong></p> <p>句点Q?code>.</code>Q或头Q?code>-></code>Q前后不要有I格Q指?地址操作W(<code>*?amp;</code>Q后不要有空根{?/p> <p>下面是指针和引用表达式的正确范例Q?/p><pre>x = *p; p = &x; x = r.y; x = r->y; </pre> <p>注意Q?/p> <p>1) 在访问成员时Q句Ҏ头前后没有I格Q?/p> <p>2) 指针操作W?code>*</code>?code>&</code>后没有空根{?/p> <p>在声明指针变量或参数Ӟ星号与类型或变量名紧挨都可以Q?/p><pre>// These are fine, space preceding. char *c; const string &str; // These are fine, space following. char* c; // but remember to do "char* c, *d, *e, ...;"! const string& str;</pre><pre>char * c; // Bad - spaces on both sides of * const string & str; // Bad - spaces on both sides of & </pre> <p>同一个文Ӟ新徏或现有)中v码要保持一致?/p> <p><strong>译者注Q个人比较习惯与变量紧挨的方?/strong><strong>?/strong></p> <p><strong><font color="#800000">9. 布尔表达式(Boolean ExpressionsQ?/font></strong></p> <p>如果一个布表辑ּ过标准行宽Q?0字符Q,如果断行要统一一下?/p> <p>下例中,逻辑与(<code>&&</code>Q操作符M于行:</p><pre>if (this_one_thing > this_other_thing && a_third_thing == a_fourth_thing && yet_another & last_one) { ... } </pre> <p>两个逻辑与(<code>&&</code>Q操作符都位于行,可以考虑额外插入圆括P合理使用的话对增强可L是很有帮助的?/p> <p><strong>译者注Q个人比较习惯逻辑q算W位于行首,逻辑关系一目了Ӟ各h喜好而已Q至于加不加圆括L问题Q如果你对优先了然于胸的话可以不加Q但可读性L差了?/strong><strong>?/strong></p> <p><strong><font color="#800000">10. 函数q回|Return ValuesQ?/font></strong></p> <p><code>return</code>表达式中不要使用圆括受?/p> <p>函数q回时不要用圆括号Q?/p><pre>return x; // not return(x); </pre> <p><strong><font color="#800000">11. 变量及数l初始化QVariable and Array InitializationQ?/font></strong></p> <p>选择<code>=</code>q是<code>()</code>?/p> <p>需要做二者之间做出选择Q下面的形式都是正确的:</p><pre>int x = 3; int x(3); string name("Some Name"); string name = "Some Name"; </pre> <p><strong><font color="#800000">12. 预处理指令(Preprocessor DirectivesQ?/font></strong></p> <p>预处理指令不要羃q,从行首开始?/p> <p>即预处理指令位于羃q代码块中,指o也应从行首开始?/p><pre>// Good - directives at beginning of line if (lopsided_score) { #if DISASTER_PENDING // Correct -- Starts at beginning of line DropEverything(); #endif BackToNormal(); }</pre><pre>// Bad - indented directives if (lopsided_score) { #if DISASTER_PENDING // Wrong! The "#if" should be at beginning of line DropEverything(); #endif // Wrong! Do not indent "#endif" BackToNormal(); } </pre> <p><strong><font color="#800000">13. cL式(Class FormatQ?/font></strong></p> <p>声明属性依ơ序?code>public:</code>?code>protected:</code>?code>private:</code>Q每ơ羃q?个空?font color="#800000">Q译者注Qؓ什么不是两个呢Q也有h提?code>private</code>在前Q对于声明了哪些数据成员一目了Ӟq有人提倡依逻辑关系变量与操作攑֜一P都有道理<code>:-)</code>Q?/font>?/p> <p>cd明(对类注释不了解的话,参?a title="[译]Google C++~程风格指南Q六Q? href="http://www.shnenglu.com/Fox/archive/2008/07/22/56873.html" target="_blank">W六?/a>中的<strong>cL?/strong>一节)的基本格式如下:</p><pre>class MyClass : public OtherClass { public: // Note the 1 space indent! MyClass(); // Regular 2 space indent. explicit MyClass(int var); ~MyClass() {} void SomeFunction(); void SomeFunctionThatDoesNothing() { } void set_some_var(int var) { some_var_ = var; } int some_var() const { return some_var_; } private: bool SomeInternalFunction(); int some_var_; int some_other_var_; DISALLOW_COPY_AND_ASSIGN(MyClass); }; </pre> <p>注意Q?/p> <p>1) 所以基cd应在80列限制下量与子cd攑֜同一行;</p> <p>2) 关键?code>public:?/code><code>protected:</code>?code>private:</code>要羃q?个空?font color="#800000">Q译者注QMSVC多用tab~进Q且q三个关键词没有~进Q?/font>Q?/p> <p>3) 除第一个关键词Q一般是<code>publicQ外Q其他关键词前空一行,如果cL较小的话也可以不I;</code></p> <p>4) q些关键词后不要IQ?/p> <p>5) <code>public</code>攑֜最前面Q然后是<code>protected</code>?code>private</code>Q?/p> <p>6) 关于声明ơ序参?a title="[译]Google C++~程风格指南Q三Q? href="http://www.shnenglu.com/Fox/archive/2008/07/16/56324.html" target="_blank">W三?/a><strong>声明ơ序</strong>一节?/p> <p><strong><font color="#800000">14. 初始化列表(Initializer ListsQ?/font></strong></p> <p>构造函数初始化列表攑֜同一行或按四格羃qƈ排几行?/p> <p>两种可以接受的初始化列表格式Q?/p><pre>// When it all fits on one line: MyClass::MyClass(int var) : some_var_(var), some_other_var_(var + 1) { </pre> <p>?/p><pre>// When it requires multiple lines, indent 4 spaces, putting the colon on // the first initializer line: MyClass::MyClass(int var) : some_var_(var), // 4 space indent some_other_var_(var + 1) { // lined up ... DoSomething(); ... } </pre> <p><strong><font color="#800000">15. 命名I间格式化(Namespace FormattingQ?/font></strong></p> <p>命名I间内容不羃q?/p> <p>命名I间不添加额外羃q层ơ,例如Q?/p><pre>namespace { void foo() { // Correct. No extra indentation within namespace. ... } } // namespace </pre> <p>不要~进Q?/p><pre>namespace { // Wrong. Indented when it should not be. void foo() { ... } } // namespace </pre> <p><strong><font color="#800000">16. 水^留白QHorizontal WhitespaceQ?/font></strong></p> <p>水^留白的用因地制宜。不要在行尾d无谓的留白?/p> <p><strong>普?/strong>Q?/p><pre>void f(bool b) { // Open braces should always have a space before them. ... int i = 0; // Semicolons usually have no space before them. int x[] = { 0 }; // Spaces inside braces for array initialization are int x[] = {0}; // optional. If you use them, put them on both sides! // Spaces around the colon in inheritance and initializer lists. class Foo : public Bar { public: // For inline function implementations, put spaces between the braces // and the implementation itself. Foo(int b) : Bar(), baz_(b) {} // No spaces inside empty braces. void Reset() { baz_ = 0; } // Spaces separating braces from implementation. ... </pre> <p>d冗余的留白会l其他h~辑旉成额外负担Q因此,不要加入多余的空根{如果确定一行代码已l修改完毕,多余的I格LQ或者在专门清理I格时去掉(信没有其他人在使用Q?/p> <p><strong>循环和条件语?/strong>Q?/p><pre>if (b) { // Space after the keyword in conditions and loops. } else { // Spaces around else. } while (test) {} // There is usually no space inside parentheses. switch (i) { for (int i = 0; i < 5; ++i) { switch ( i ) { // Loops and conditions may have spaces inside if ( test ) { // parentheses, but this is rare. Be consistent. for ( int i = 0; i < 5; ++i ) { for ( ; i < 5 ; ++i) { // For loops always have a space after the ... // semicolon, and may have a space before the // semicolon. switch (i) { case 1: // No space before colon in a switch case. ... case 2: break; // Use a space after a colon if there's code after it. </pre> <p><strong>操作W?/strong>Q?/p><pre>x = 0; // Assignment operators always have spaces around // them. x = -5; // No spaces separating unary operators and their ++x; // arguments. if (x && !y) ... v = w * x + y / z; // Binary operators usually have spaces around them, v = w*x + y/z; // but it's okay to remove spaces around factors. v = w * (x + z); // Parentheses should have no spaces inside them. </pre> <p><strong>模板和{?/strong>Q?/p><pre>vector<string> x; // No spaces inside the angle y = static_cast<char*>(x); // brackets (< and >), before // <, or between >( in a cast. vector<char *> x; // Spaces between type and pointer are // okay, but be consistent. set<list<string> > x; // C++ requires a space in > >. set< list<string> > x; // You may optionally make use // symmetric spacing in < <. </pre> <p><strong><font color="#800000">17. 垂直留白QVertical WhitespaceQ?/font></strong></p> <p>垂直留白少好?/p> <p>q不仅仅是规则而是原则问题了:不是非常有必要的话就不要使用I。尤其是Q不要在两个函数定义之间Iq?行,函数体头、尾不要有空行,函数体中也不要随意添加空行?/p> <p>基本原则是:同一屏可以显C多的代码Q程序的控制就容易理解。当Ӟq于密集的代码块和过于疏杄代码块同样难看,取决于你的判断,但通常是越越好?/p> <p>函数头、尾不要有空行:</p><pre>void Function() { // Unnecessary blank lines before and after } </pre> <p>代码块头、尾不要有空行:</p><pre>while (condition) { // Unnecessary blank line after } if (condition) { // Unnecessary blank line before } </pre> <p><code>if-else</code>块之间空一行还可以接受Q?/p><pre>if (condition) { // Some lines of code too small to move to another function, // followed by a blank line. } else { // Another block of code } </pre> <p>______________________________________ </p> <p>译者:首先说明Q对于代码格式,因h、因pȝ各有优缺点,但同一个项目中遵@同一标准q是有必要的Q? <p><strong>1. 行宽原则上不过80列,?2寸的昄屏都占完Q怎么也说不过去;</strong></p> <p><strong>2. 量不用非ASCII字符Q如果用的话,参考UTF-8格式Q尤其是UNIX/Linux下,Windows下可以考虑宽字W)Q尽量不字W串帔R耦合C码中Q比如独立出资源文gQ这不仅仅是风格问题了;</strong></p> <p><strong>3. UNIX/Linux下无条g使用I格QMSVC的话使用Tab也无可厚非;</strong></p> <p><strong>4. 函数参数、逻辑条g、初始化列表Q要么所有参数和函数名放在同一行,要么所有参数ƈ排分行;</strong></p> <p><strong>5. 除函数定义的左大括号可以|于行首外,包括函数/c?l构?枚D声明、各U语句的左大括号|于行尾Q所有右大括L立成行;</strong></p> <p><strong>6. ./->操作W前后不留空|*/&不要前后都留Q一个就可,靠左靠右依各人喜好;</strong></p> <p><strong>7. 预处理指?命名I间不用额外羃q,c?l构?枚D/函数/语句使用~进Q?/strong></p> <p><strong>8. 初始化用=q是()依个人喜好,l一好Q?/strong></p> <p><strong>9. return不要?)Q?/strong></p> <p><strong>10. 水^/垂直留白不要滥用Q怎么易读怎么来?/strong></p><img src ="http://www.shnenglu.com/Fox/aggbug/56922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-07-23 11:43 <a href="http://www.shnenglu.com/Fox/archive/2008/07/23/56922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[译]Google C++~程风格指南Q六Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/07/22/56873.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Tue, 22 Jul 2008 09:02:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/07/22/56873.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/56873.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/07/22/56873.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/56873.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/56873.html</trackback:ping><description><![CDATA[<p>原文地址Q?a title="Google C++ Style Guide" target="_blank" rel="tag">Google C++ Style Guide</a></p> <ul> <li><strong><font color="#800000">注释</font></strong></li></ul> <p>注释虽然写v来很痛苦Q但对保证代码可L至为重要,下面的规则描qC应该注释什么、注释在哪儿。当然也要记住,注释的确很重要,但最好的代码<font color="#800000">本n是文档Qself-documentingQ?/font>Q类型和变量命名意义明确要比通过注释解释模糊的命名好得多?/p> <p>注释是ؓ别hQ下一个需要理解你的代码的人)而写的,认真点吧Q那下一个h可能是你!</p> <p><strong><font color="#800000">1. 注释风格QComment StyleQ?/font></strong></p> <p>使用<code>//</code>?code>/* */</code>Q统一好?/p> <p><code>//</code>?code>/* */</code>都可以,<code>//</code>只是用的更加q泛Q在如何注释和注释风g保l一?/p> <p></p> <p><strong><font color="#800000">2. 文g注释QFile CommentsQ?/font></strong> <p>在每一个文件开头加入版权公告,然后是文件内Ҏq?/p> <p><strong>法律公告和作者信?/strong>Q?/p> <p>每一文g包含以下,依次是:</p> <p>1) <font color="#800000">版权Qcopyright statementQ?/font>Q如<code>Copyright 2008 Google Inc.</code>Q?/p> <p>2) <font color="#800000">许可版本Qlicense boilerplateQ?/font>Qؓ目选择合适的许可证版本,?a title="Apache License" target="_blank">Apache 2.0</a>?a title="BSD licenses" target="_blank">BSD</a>?a title="GNU Lesser General Public License" target="_blank">LGPL</a>?a title="GNU General Public License" target="_blank">GPL</a>Q?/p> <p>3) <font color="#800000">作者(author lineQ?/font>Q标识文件的原始作者?/p> <p>如果你对其他人创建的文g做了重大修改Q将你的信息dC者信息里Q这样当其他人对该文件有疑问时可以知道该联系谁?/p> <p><strong>文g内容</strong>Q?/p> <p>每一个文件版权许可及作者信息后Q都要对文g内容q行注释说明?/p> <p>通常Q?code>.h</code>文g要对所声明的类的功能和用法作简单说明,<code>.cc</code>文g包含了更多的实现l节或算法讨论,如果你感觉这些实现细节或法讨论对于阅读有帮助,可以?code>.cc</code>中的注释攑ֈ<code>.h</code>中,q在<code>.cc</code>中指出文档在<code>.h</code>中?/p> <p>不要单纯?code>.h</code>?code>.cc</code>间复制注释,复制的注释偏M实际意义?/p> <p><strong><font color="#800000">3. cL释(Class CommentsQ?/font></strong></p> <p>每个cȝ定义要附着描述cȝ功能和用法的注释?/p><pre>// Iterates over the contents of a GargantuanTable. Sample usage: // GargantuanTable_Iterator* iter = table->NewIterator(); // for (iter->Seek("foo"); !iter->done(); iter->Next()) { // process(iter->key(), iter->value()); // } // delete iter; class GargantuanTable_Iterator { ... }; </pre> <p>如果你觉得已l在文g剙详细描述了该c,想直接简单的来上一句“完整描q见文g剙”的话,q是多少在类中加Ҏ释吧?/p> <p>如果cLM<font color="#800000">同步前提Qsynchronization assumptionsQ?/font>Q文档说明之。如果该cȝ实例可被多线E访问,使用时务必注意文档说明?/p> <p><strong><font color="#800000">4. 函数注释QFunction CommentsQ?/font></strong></p> <p>函数声明处注释描q函数功能,定义处描q函数实现?/p> <p><strong>函数声明</strong>Q?/p> <p>注释于声明之前,描述函数功能及用法,注释使用描述式("Opens the file"Q而非指o式("Open the file"Q;注释只是Z描述函数而不是告诉函数做什么。通常Q注释不会描q函数如何实玎ͼ那是定义部分的事情?/p> <p>函数声明处注释的内容Q?/p> <p>1) <font color="#800000">inputsQ输入)</font>?font color="#800000">outputsQ输出)</font>Q?/p> <p>2) 对类成员函数而言Q函数调用期间对象是否需要保持引用参敎ͼ是否会释放这些参敎ͼ</p> <p>3) 如果函数分配了空_需要由调用者释放;</p> <p>4) 参数是否可以?code>NULL</code>Q?/p> <p>5) 是否存在函数使用?font color="#800000">性能隐忧Qperformance implicationsQ?/font>Q?/p> <p>6) 如果函数?font color="#800000">可重入的Qre-entrantQ?/font>Q其<font color="#800000">同步前提Qsynchronization assumptionsQ?/font>是什么?</p> <p>举例如下Q?/p><pre>// Returns an iterator for this table. It is the client's // responsibility to delete the iterator when it is done with it, // and it must not use the iterator once the GargantuanTable object // on which the iterator was created has been deleted. // // The iterator is initially positioned at the beginning of the table. // // This method is equivalent to: // Iterator* iter = table->NewIterator(); // iter->Seek(""); // return iter; // If you are going to immediately seek to another place in the // returned iterator, it will be faster to use NewIterator() // and avoid the extra seek. Iterator* GetIterator() const; </pre> <p>但不要有无谓冗余或显而易见的注释Q下面的注释没有必要加上“returns false otherwise”,因ؓ已经暗含其中了:</p><pre>// Returns true if the table cannot hold any more entries. bool IsTableFull(); </pre> <p>注释构?析构函数ӞCQ读代码的h知道构?析构函数是什么,所以“destroys this object”这L注释是没有意义的。说明构造函数对参数做了什么(例如Q是否是指针的所有者)以及析构函数清理了什么,如果都是无关紧要的内容,直接省掉注释Q析构函数前没有注释是很正常的?/p> <p><strong>函数定义</strong>Q?/p> <p>每个函数定义时要以注释说明函数功能和实现要点Q如使用的漂亮代码、实现的要步骤、如此实现的理由、ؓ什么前半部分要加锁而后半部分不需要?/p> <p>不要?code>.h</code>文g或其他地方的函数声明处直接复制注释,要说明函数功能是可以的,但重点要攑֜如何实现上?/p> <p><strong><font color="#800000">5. 变量注释QVariable CommentsQ?/font></strong></p> <p>通常变量名本w以很好说明变量用途,特定情况下,需要额外注释说明?/p> <p><strong>cL据成?/strong>Q?/p> <p>每个cL据成员(也叫实例变量或成员变量)应注释说明用途,如果变量可以接受<code>NULL</code>?1{?font color="#800000">警戒|sentinel valuesQ?/font>Q须说明之,如:</p><pre>private: // Keeps track of the total number of entries in the table. // Used to ensure we do not go over the limit. -1 means // that we don't yet know how many entries the table has. int num_total_entries_; </pre> <p><strong>全局变量Q常量)</strong>Q?/p> <p>和数据成员相|所有全局变量Q常量)也应注释说明含义及用途,如:</p><pre>// The total number of tests cases that we run through in this regression test. const int kNumTestCases = 6; </pre> <p><strong><font color="#800000">6. 实现注释QImplementation CommentsQ?/font></strong></p> <p>对于实现代码中y妙的、晦涩的、有的、重要的地方加以注释?/p> <p><strong>代码前注?/strong>Q?/p> <p>出彩的或复杂的代码块前要加注释,如:</p><pre>// Divide result by two, taking into account that x // contains the carry from the add. for (int i = 0; i < result->size(); i++) { x = (x << 8) + (*result)[i]; (*result)[i] = x >> 1; x &= 1; } </pre> <p><strong>行注?/strong>Q?/p> <p>比较隐晦的地方要在行֊入注释,可以在代码之后空两格加行注释,如:</p><pre>// If we have enough memory, mmap the data portion too. mmap_budget = max<int64>(0, mmap_budget - index_->length()); if (mmap_budget >= data_size_ && !MmapData(mmap_chunk_bytes, mlock)) return; // Error already logged. </pre> <p>注意Q有两块注释描述q段代码Q当函数q回时注释提及错误已l被记入日志?/p> <p>前后盔R几行都有注释Q可以适当调整使之可读性更好:</p><pre>... DoSomething(); // Comment here so the comments line up. DoSomethingElseThatIsLonger(); // Comment here so there are two spaces between // the code and the comment. ... </pre> <p><strong>NULL、true/false???…?/strong>Q?/p> <p>向函C入、布值或整数Ӟ要注释说明含义,或用常量让代码望文知意Q比较一下:</p><pre>bool success = CalculateSomething(interesting_value, 10, false, NULL); // What are these arguments?? </pre> <p>和:</p><pre>bool success = CalculateSomething(interesting_value, 10, // Default base value. false, // Not the first time we're calling this. NULL); // No callback. </pre> <p>使用帔R或描q性变量:</p><pre>const int kDefaultBaseValue = 10; const bool kFirstTimeCalling = false; Callback *null_callback = NULL; bool success = CalculateSomething(interesting_value, kDefaultBaseValue, kFirstTimeCalling, null_callback); </pre> <p><strong>不要</strong>Q?/p> <p>注意永远不要用自然语a译代码作ؓ注释Q要假设M代码的hC++比你?DQ?/p><pre>// Now go through the b array and make sure that if i occurs, // the next element is i+1. ... // Geez. What a useless comment. </pre> <p><strong><font color="#800000">7. 标点、拼写和语法QPunctuation, Spelling and GrammarQ?/font></strong></p> <p>留意标点、拼写和语法Q写的好的注释比差的要易ȝ多?/p> <p>注释一般是包含适当大写和句点(.Q的完整的句子,短一点的注释Q如代码行尾的注释)可以随意点,依然要注意风格的一致性。完整的句子可读性更好,也可以说明该注释是完整的而不是一点不成熟的想法?/p> <p>虽然被别人指?font color="#800000">分号QsemicolonQ?/font>的时候用?font color="#800000">逗号QcommaQ?/font>有点尬。清晰易ȝ代码q是很重要的Q适当的标炏V拼写和语法Ҏ会有所帮助?/p> <p><strong><font color="#800000">8. TODO注释QTODO CommentsQ?/font></strong></p> <p>寚w些时的、短期的解决ҎQ或已经够好但ƈ不完的代码使用<code>TODO</code>注释?/p> <p>q样的注释要使用全大写的字符?code>TODO</code>Q后?font color="#800000">括号QparenthesesQ?/font>里加上你的大名、邮件地址{,q可以加?font color="#800000">冒号QcolonQ?/font>Q目的是可以Ҏl一?code>TODO</code>格式q行查找Q?/p><pre>// TODO(kl@gmail.com): Use a "*" here for concatenation operator. // TODO(Zeke) change this to use relations. </pre> <p>如果加上是ؓ了在“将来某一天做某事”,可以加上一个特定的旉Q?Fix by November 2005"Q或事gQ?Remove this code when all clients can handle XML responses."Q?/p> <p>______________________________________ </p> <p>译者:注释也是比较人性化的约定了Q? <p><strong>1. 关于注释风格Q很多C++的coders更喜Ƣ行注释QC coders或许对块注释依然情有独钟Q或者在文g头大D大D늚注释时用块注释Q?/strong></p> <p><strong>2. </strong><strong>文g注释可以炫耀你的成就Q也是ؓ了捅了篓子别人可以找你;</strong></p> <p><strong>3. 注释要言意赅Q不要拖沓冗余,复杂的东西简单化和简单的东西复杂化都是要被鄙视的Q?/strong></p> <p><strong>4. 对于Chinese coders来说Q用英文注释q是用中文注释,it is a problemQ但不管怎样Q注释是Z让别人看懂,N是ؓ了炫耀~程语言之外的你的母语或外语水^吗;</strong></p> <p><strong>5. 注释不要太ؕQ适当的羃q才会让Z意看Q但也没有必要规定注释从W几列开始(我自己写代码的时候dƢ这PQUNIX/LINUX下还可以U定是用tabq是spaceQ个人們֐于spaceQ?/strong></p> <p><strong>6. TODO很不错,有时候,注释实是ؓ了标C些未完成的或完成的不如人意的地方,q样一搜烦Q就知道q有哪些z要qԌ日志都省了?/strong></p><img src ="http://www.shnenglu.com/Fox/aggbug/56873.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-07-22 17:02 <a href="http://www.shnenglu.com/Fox/archive/2008/07/22/56873.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[译]Google C++~程风格指南Q五Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/07/22/56845.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Tue, 22 Jul 2008 03:59:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/07/22/56845.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/56845.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/07/22/56845.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/56845.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/56845.html</trackback:ping><description><![CDATA[<p>原文地址Q?a title="Google C++ Style Guide" target="_blank" rel="tag">Google C++ Style Guide</a></p> <ul> <li><strong><font color="#800000">命名U定</font></strong></li></ul> <p>最重要的一致性规则是命名理Q命名风格直接可以直接确定命名实体是Q类型、变量、函数、常量、宏{等Q无需查找实体声明Q我们大脑中的模式匹配引擎依赖于q些命名规则?/p> <p>命名规则h一定随意性,但相比按个h喜好命名Q一致性更重要Q所以不你怎么惻I规则d是规则?/p> <p><strong><font color="#800000">1. 通用命名规则QGeneral Naming RulesQ?/font></strong></p> <p>函数命名、变量命名、文件命名应h描述性,不要q度~写Q类型和变量应该是名词,函数名可以用“命令性”动词?/p> <p><strong>如何命名</strong>Q? <p>可能给出描q性名Uͼ不要节约I间Q让别h很快理解你的代码更重要,好的命名选择Q?pre>int num_errors; // Good. int num_completed_connections; // Good.</pre> <p></p> <p>丑陋的命名用模p的~写或随意的字符Q?pre>int n; // Bad - meaningless. int nerr; // Bad - ambiguous abbreviation. int n_comp_conns; // Bad - ambiguous abbreviation.</pre> <p></p> <p>cd和变量名一般ؓ名词Q如<code>FileOpener</code>?code>num_errors</code>? <p>函数名通常是指令性的Q如<code>OpenFile()</code>?code>set_num_errors()</code>Q访问函数需要描q的更细_要与其访问的变量相吻合? <p><strong>~写</strong>Q? <p>除非攑ֈ目外也非常明了Q否则不要用羃写,例如Q?pre>// Good // These show proper names with no abbreviations. int num_dns_connections; // Most people know what "DNS" stands for. int price_count_reader; // OK, price count. Makes sense.</pre><pre> </pre><pre>// Bad! // Abbreviations can be confusing or ambiguous outside a small group. int wgc_connections; // Only your group knows what this stands for. int pc_reader; // Lots of things can be abbreviated "pc".</pre> <p></p> <p>不要用省略字母的~写Q?pre>int error_count; // Good.</pre><pre>int error_cnt; // Bad.</pre> <p></p> <p><strong><font color="#800000">2. 文g命名QFile NamesQ?/font></strong> <p>文g名要全部写Q可以包含下划线Q_Q或短线Q?Q,按项目约定来?/p> <p>可接受的文g命名Q?/p> <p><code>my_useful_class.cc<br>my-useful-class.cc<br>myusefulclass.cc</code></p> <p>C++文g?code>.cc</code>l尾Q头文g?code>.h</code>l尾?/p> <p>不要使用已经存在?code>/usr/include</code>下的文g?font color="#800000">Q译者注Q对UNIX、Linux{系l而言Q?/font>Q如<code>db.h</code>?/p> <p>通常Q尽量让文g名更加明,<code>http_server_logs.h</code>比<code>logs.h</code>要好Q定义类时文件名一般成对出玎ͼ?code>foo_bar.h</code>?code>foo_bar.cc</code>Q对应类<code>FooBar</code>?/p> <p>内联函数必须攑֜<code>.h</code>文g中,如果内联函数比较短,q接放?code>.h</code>中。如果代码比较长Q可以放C<code>-inl.h</code>l尾的文件中。对于包含大量内联代码的c,可以有三个文Ӟ</p><pre>url_table.h // The class declaration. url_table.cc // The class definition. url_table-inl.h // Inline functions that include lots of code.</pre> <p></p> <p>参?a title="[译]Google C++~程风格指南Q一Q? href="http://www.shnenglu.com/Fox/archive/2008/07/10/55818.html" target="_blank">W一?/a><strong>-inl.h文g</strong>一节?/p> <p><strong><font color="#800000">3. cd命名QType NamesQ?/font></strong></p> <p>cd命名每个单词以大写字母开_不包含下划线Q?code>MyExcitingClass</code>?code>MyExcitingEnum</code>?/p> <p>所有类型命名——类、结构体、类型定义(typedefQ、枚䏀—用相同约定,例如Q?/p> <p><pre>// classes and structs class UrlTable { ... class UrlTableTester { ... struct UrlTableProperties { ... // typedefs typedef hash_map<UrlTableProperties *, string> PropertiesMap; // enums enum UrlTableErrors { ...</pre> <p></p> <p><strong><font color="#800000">4. 变量命名QVariable NamesQ?/font></strong></p> <p>变量名一律小写,单词间以下划U相q,cȝ成员变量以下划线l尾Q如<code>my_exciting_local_variable</code>?code>my_exciting_member_variable_</code>?/p> <p><strong>普通变量命?/strong>Q?/p> <p>举例Q?/p><pre>string table_name; // OK - uses underscore. string tablename; // OK - all lowercase.</pre><pre>string tableName; // Bad - mixed case.</pre> <p></p> <p></p> <p><strong>cL据成?/strong>Q?/p> <p>l构体的数据成员可以和普通变量一P不用像类那样接下划线Q?/p><pre>struct UrlTableProperties { string name; int num_entries; }</pre> <p></p> <p>l构体与cȝ讨论参?a title="[译]Google C++~程风格指南Q三Q? href="http://www.shnenglu.com/Fox/archive/2008/07/16/56324.html" target="_blank">W三?/a><strong>l构体vs.c?/strong>一节?/p> <p><strong>全局变量</strong>Q?/p> <p>对全局变量没有特别要求Q少用就好,可以?code>g_</code>或其他易与局部变量区分的标志为前~?/p> <p><strong><font color="#800000">5. 帔R命名QConstant NamesQ?/font></strong></p> <p>在名U前?code>k</code>Q?code>kDaysInAWeek</code>?/p> <p>所有编译时帔RQ无论是局部的、全局的还是类中的Q和其他变量保持些许区别Q?code>k</code>后接大写字母开头的单词Q?/p><pre>const int kDaysInAWeek = 7;</pre> <p></p> <p><strong><font color="#800000">6. 函数命名QFunction NamesQ?/font></strong></p> <p><font color="#800000">普通函敎ͼregular functionsQ译者注Q这里与讉K函数{特D函数相对)</font>大小写؜合,<font color="#800000">存取函数Qaccessors and mutatorsQ?/font>则要求与变量名匹配:<code>MyExcitingFunction()</code>?code>MyExcitingMethod()</code>?code>my_exciting_member_variable()</code>?code>set_my_exciting_member_variable()</code>?/p> <p><strong>普通函?/strong>Q?/p> <p>函数名以大写字母开_每个单词首字母大写,没有下划U:</p><pre>AddTableEntry() DeleteUrl()</pre> <p></p> <p><strong>存取函数</strong>Q?/p> <p>存取函数要与存取的变量名匚wQ这儿摘录一个拥有实例变?code>num_entries_</code>的类Q?/p><pre>class MyClass { public: ... int num_entries() const { return num_entries_; } void set_num_entries(int num_entries) { num_entries_ = num_entries; } private: int num_entries_; };</pre> <p></p> <p>其他短小的内联函数名也可以用小写字母,例如Q在循环中调用这L函数甚至都不需要缓存其|写命名可以接受?/p> <p><strong>译者注Q从q一点上可以看出Q小写的函数名意味着可以直接内联使用?/strong></p> <p><strong><font color="#800000">7. 命名I间QNamespace NamesQ?/font></strong></p> <p>命名I间的名U是全小写的Q其命名Z目名称和目录结构:<code>google_awesome_project</code>?/p> <p>关于命名I间的讨论和如何命名Q参?a title="[译]Google C++~程风格指南Q二Q? href="http://www.shnenglu.com/Fox/archive/2008/07/14/56109.html" target="_blank">W二?/a><strong>命名I间</strong>?/p> <p><strong><font color="#800000">8. 枚D命名QEnumerator NamesQ?/font></strong></p> <p>枚D值应全部大写Q单词间以下划线相连Q?code>MY_EXCITING_ENUM_VALUE</code>?/p> <p>枚D名称属于cdQ因此大写混合Q?code>UrlTableErrors</code>?/p><pre>enum UrlTableErrors { OK = 0, ERROR_OUT_OF_MEMORY, ERROR_MALFORMED_INPUT, };</pre> <p></p> <p><strong><font color="#800000">9. 宏命名(Macro NamesQ?/font></strong></p> <p>你ƈ不打用宏Q对吧?如果使用Q像q样Q?code>MY_MACRO_THAT_SCARES_SMALL_CHILDREN</code>?/p> <p>参?a title="[译]Google C++~程风格指南Q四Q? href="http://www.shnenglu.com/Fox/archive/2008/07/21/56760.html" target="_blank">W四?/a><strong>预处理宏</strong>Q通常是不使用宏的Q如果绝对要用,其命名像枚D命名一样全部大写、用下划线Q?/p> <p><pre>#define ROUND(x) ... #define PI_ROUNDED 3.0 MY_EXCITING_ENUM_VALUE</pre> <p></p> <p><strong><font color="#800000">10. 命名规则例外QExceptions to Naming RulesQ?/font></strong></p> <p>当命名与现有C/C++实体怼的对象时Q可参考现有命名约定: <dl> <dt><code>bigopen()</code> <dd>函数名,参?code>open()</code> <dt><code>uint</code> <dd><code>typedefcd定义</code> <dt><code>bigpos</code> <dd><code>struct</code>?code>classQ参?/code><code>pos</code> <dt><code>sparse_hash_map</code> <dd>STL怼实体Q参考STL命名U定 <dt><code>LONGLONG_MAX</code> <dd>帔RQ类?code>INT_MAX</code></dd></dl> <p>______________________________________ </p> <p>译者:命名U定q对轻松许多,在遵从代码一致性、可L的前提下,略显随意Q? <p><strong>1. M规则Q不要随意羃写,如果说ChangeLocalValue写作ChgLocValq有情可原的话,把ModifyPlayerName写作MdfPlyNm太q分了,除函数名可适当为动词外Q其他命名尽量用清晰易懂的名词Q?/strong></p> <p><strong>2. </strong><strong>宏、枚丄使用全部大写+下划U;</strong></p> <p><strong>3. 变量Q含cR结构体成员变量Q、文件、命名空间、存取函数等使用全部写+下划U,cL员变量以下划U结,全局变量以g_开_</strong></p> <p><strong>4. 普通函数、类型(含类与结构体、枚丄型)、常量等使用大小写؜合,不含下划U;</strong></p> <p><strong>5. 参考现有或相近命名U定?/strong></p><img src ="http://www.shnenglu.com/Fox/aggbug/56845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-07-22 11:59 <a href="http://www.shnenglu.com/Fox/archive/2008/07/22/56845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[译]Google C++~程风格指南Q四Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/07/21/56760.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Mon, 21 Jul 2008 06:55:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/07/21/56760.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/56760.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/07/21/56760.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/56760.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/56760.html</trackback:ping><description><![CDATA[<p>原文地址Q?a title="Google C++ Style Guide" target="_blank" rel="tag">Google C++ Style Guide</a></p> <ul> <li><strong><font color="#800000">GoogleҎ的风?/font></strong></li></ul> <p>Google有很多自己实现的使C++代码更加健壮的技巧、功能,以及有异于别处的C++的用方式?/p> <p><strong><font color="#800000">1. 指针QSmart PointersQ?/font></strong></p> <p>如果实需要用智能指针的话,scoped_ptr完全可以胜Q。在非常Ҏ的情况下Q例如对STL容器中对象,你应该只使用std::tr1::shared_ptrQQ何情况下都不要用auto_ptr?/p> <p>“智能”指针看上去是指针,其实是附加了语义的对象。以scoped_ptrZQscoped_ptr被销毁时Q删除了它所指向的对象。shared_ptr也是如此Q而且Qshared_ptr实现?font color="#800000">引用计数Qreference-countingQ?/font>Q从而只有当它所指向的最后一个对象被销毁时Q指针才会被删除?/p> <p>一般来_我们們֐于设计对象隶属明的代码Q最明确的对象隶属是Ҏ不用指针,直接对象作Z?font color="#800000">域(fieldQ?/font>或局部变量用。另一U极端是引用计数指针不属于Q何对象,q样设计的问题是ҎD循环引用或其他导致对象无法删除的诡异条gQ而且在每一ơ拷贝或赋值时q原子操作都会很慢?/p> <p>虽然不推荐这么做Q但有些时候,引用计数指针是最单有效的解决Ҏ? <p><strong>译者注Q看来,Google所谓的不同之处Q在于尽量避免用智能指?DQ用时也尽量局部化Qƈ且,安全W一?/strong> <ul> <li><strong><font color="#800000">其他C++Ҏ?/font></strong></li></ul> <p><strong><font color="#800000">1. 引用参数QReference ArgumentsQ?/font></strong></p> <p>所以按引用传递的参数必须加上const?/p> <p><strong>定义Q?/strong>在C语言中,如果函数需要修改变量的|<font color="#800000">形参QparameterQ?/font>必须为指针,如int foo(int *pval)。在C++中,函数q可以声明引用Ş参:int foo(int &val)?/p> <p><strong>优点Q?/strong>定义形参为引用避免了?*pval)++q样丑陋的代码,像拷贝构造函数这L应用也是必需的,而且不像指针那样不接受空指针NULL?/p> <p><strong>~点Q?/strong>Ҏ引v误解Q因为引用在语法上是值却拥有指针的语义?/p> <p><strong>l论Q?/strong></p> <p>函数形参表中Q所有引用必LconstQ?/p><code> <p>void Foo(const string &in, string *out);</p></code> <p>事实上这是一个硬性约定:输入参数为值或常数引用Q输出参Cؓ指针Q输入参数可以是常数指针Q但不能使用非常数引用Ş参?/p> <p>在强调参C是拷贝而来Q在对象生命期内必须一直存在时可以使用常数指针Q最好将q些在注释中详细说明。bind2nd和mem_fun{STL适配器不接受引用形参Q这U情况下也必M指针形参声明函数?/p> <p><strong><font color="#800000">2. 函数重蝲QFunction OverloadingQ?/font></strong></p> <p>仅在输入参数cd不同、功能相同时使用重蝲函数Q含构造函敎ͼQ不要用函数重载模仿缺省函数参数?/p> <p><strong>定义Q?/strong>可以定义一个函数参数类型ؓconst string&Qƈ定义光载函数类型ؓconst char*?/p><code> <p>class MyClass {<br>public:<br>  void Analyze(const string &text);<br>  void Analyze(const char *text, size_t textlen);<br>};</p></code> <p><strong>优点Q?/strong>通过重蝲不同参数的同名函敎ͼ令代码更加直观,模板化代码需要重载,同时问者带来便利?/p> <p><strong>~点Q?/strong>限制使用重蝲的一个原因是在特定调用处很难定到底调用的是哪个函数Q另一个原因是当派生类只重载函数的部分变量会o很多人对l承语义产生困惑。此外在阅读库的客户端代码时Q因~省函数参数造成不必要的费解?/p> <p><strong>l论Q?/strong>如果你想重蝲一个函敎ͼ考虑让函数名包含参数信息Q例如,使用AppendString()、AppendInt()而不是Append()?/p> <p><strong><font color="#800000">3. ~省参数QDefault ArgumentsQ?/font></strong></p> <p>止使用~省函数参数?/p> <p><strong>优点Q?/strong>l常用到一个函数带有大量缺省|偶尔会重写一下这些|~省参数为很涉及的例外情况提供了少定义一些函数的方便? <p><strong>~点Q?/strong>大家l常会通过查看现有代码定如何使用APIQ缺省参C得复制粘贴以前的代码难以呈现所有参敎ͼ当缺省参C适用于新代码时可能导致重大问题? <p><strong>l论Q?/strong>所有参数必L指定,强制E序员考虑API和传入的各参数|避免使用可能不ؓE序员所知的~省参数? <p><strong><font color="#800000">4. 变长数组和allocaQVariable-Length Arrays and alloca()Q?/font></strong></p> <p>止使用变长数组和alloca()?/p> <p><strong>优点Q?/strong>变长数组h然天成的语法,变长数组和alloca()也都很高效?/p> <p><strong>~点Q?/strong>变长数组和alloca()不是标准C++的组成部分,更重要的是,它们?font color="#800000">堆栈QstackQ?/font>上根据数据分配大可能导致难以发现的内存泄漏Q“在我的机器上运行的好好的,C产品中却莫名其妙的挂掉了”?/p> <p><strong>l论Q?/strong></p> <p>使用安全?font color="#800000">分配器(allocatorQ?/font>Q如scoped_ptr/scoped_array? <p><strong><font color="#800000">5. 友元QFriendsQ?/font></strong></p> <p>允许合理使用友元cd友元函数?/p> <p>通常友元定义在同一文g下,避免读者跑到其他文件中查找其对某个cȝ有成员的使用。经常用到友元的一个地ҎFooBuilder声明为Foo的友元,FooBuilder以便可以正确构造Foo的内部状态,而无需该状态暴露出来。某些情况下Q将一个单元测试用cd明ؓ待测cȝ友元会很方便?/p> <p>友元延了(但没有打_cȝ装界线Q当你希望只允许另一个类讉K某个成员Ӟ使用友元通常比将其声明ؓpublic要好得多。当Ӟ大多数类应该只提供公共成员与其交互? <p><strong><font color="#800000">6. 异常QExceptions</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>不要使用C++异常?/p> <p><strong>优点Q?/strong></p> <p>1) 异常允许上层应用军_如何处理在底层嵌套函C发生的“不可能发生”的p|Q不像出错代码的记录那么模糊费解Q?/p> <p>2) 应用于其他很多现代语a中,引入异常使得C++与Python、Java及其他与C++相近的语a更加兼容Q?/p> <p>3) 许多C++W三方库使用异常Q关闭异常将D难以与之l合Q?/p> <p>4) 异常是解x造函数失败的唯一ҎQ虽然可以通过<font color="#800000">工厂函数Qfactory functionQ?/font>或Init()Ҏ模拟异常Q但他们分别需要堆分配或新的“非法”状态;</p> <p>5) ?font color="#800000">试框架Qtesting frameworkQ?/font>中,异常实很好用?/p> <p><strong>~点Q?/strong></p> <p>1) 在现有函Cdthrow语句Ӟ必须查所有调用处Q即使它们至具有基本的异常安全保护Q或者程序正常结束,永远不可能捕莯异常。例如:if <code>f()</code> calls <code>g()</code> calls <code>h()</code>Q?code>h</code>抛出?code>f</code>捕获的异常,<code>g</code>p当心了,避免没有完全清理Q?/p> <p>2) 通俗一点说Q异怼DE序<font color="#800000">控制(control flowQ?/font>通过查看代码无法定Q函数有可能在不定的地方返回,从而导致代码管理和调试困难Q当Ӟ你可以通过规定何时何地如何使用异常来最化的降低开销Q却l开发h员带来掌握这些规定的负担Q?/p> <p>3) 异常安全需要RAII和不同编码实c轻松、正编写异常安全代码需要大量支撑。允怋用异常;</p> <p>4) 加入异常使二q制执行代码体积变大Q增加了~译旉Q或许媄响不大)Q还可能增加地址I间压力Q?/p> <p>5) 异常的实用性可能会刺激开发h员在不恰当的时候抛出异常,或者在不安全的地方从异怸恢复Q例如,非法用户输入可能D抛出异常。如果允怋用异怼使得q样一编E风格指南长出很多(<font color="#800000">译者注Q这个理由有点牵?-(</font>Q!</p> <p><strong>l论Q?/strong></p> <p>从表面上看,使用异常利大于弊Q尤其是在新目中,然而,对于现有代码Q引入异怼牵连到所有依赖代码。如果允许异常在新项目中使用Q在跟以前没有用异常的代码整合时也是一个麻烦。因为Google现有的大多数C++代码都没有异常处理,引入带有异常处理的新代码相当困难? <p>鉴于Google现有代码不接受异常,在现有代码中使用异常比在新项目中使用的代价多要大一点,q移q程会比较慢Q也Ҏ出错。我们也不相信异常的有效替代ҎQ如错误代码、断a{,都是严重负担? <p>我们q不是基于哲学或道d层面反对使用异常Q而是在实늚基础上。因为我们希望用Google上的开源项目,但项目中使用异常会ؓ此带来不便,因ؓ我们也徏议不要在Google上的开源项目中使用异常Q如果我们需要把q些目推倒重来显然不太现实? <p>对于Windows代码来说Q这一Ҏ个例外({到最后一吧:DQ? <p><strong>译者注Q对于异常处理,昄不是短短几句话能够说清楚的,以构造函Cؓ例,很多C++书籍上都提到当构造失败时只有异常可以处理QGoogle止使用异常q一点,仅仅是ؓ了自w的方便Q说大了Q无非是Z软g理成本上,实际使用中还是自己决定?/strong> <p><strong><font color="#800000">7. q行时类型识别(Run-Time Type Information, RTTI</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>我们止使用RTTI?/p> <p><strong>定义Q?/strong>RTTI允许E序员在q行时识别C++cd象的cd?/p> <p><strong>优点Q?/strong></p> <p>RTTI在某些单元测试中非常有用Q如在进行工厂类试时用于检验一个新建对象是否ؓ期望的动态类型?/p> <p>除测试外Q极用到?/p> <p><strong>~点Q?/strong>q行时识别类型意呌设计本n有问题,如果你需要在q行期间定一个对象的cdQ这通常说明你需要重新考虑你的cȝ设计?/p> <p><strong>l论Q?/strong></p> <p>除单元测试外Q不要用RTTIQ如果你发现需要所写代码因对象cd不同而动作各异的话,考虑换一U方式识别对象类型?/p> <p>虚函数可以实现随子类cd不同而执行不同代码,工作都是交给对象本nd成?/p> <p>如果工作在对象之外的代码中完成,考虑双重分发ҎQ如Visitor模式Q可以方便的在对象本w之外确定类的类型?/p> <p>如果你认Z面的Ҏ你掌握不了,可以使用RTTIQ但务必请三思,不要L工实C?font color="#800000">貌似RTTI的方案(RTTI-like workaroundQ?/font>Q我们反对用RTTIQ同样反对脓上类型标{貌似cȝ承的替代ҎQ?font color="#800000">译者注Q用就使用吧,不用也不要造轮?D</font>Q?/p> <p><font color="#800000"><strong>8. cd转换QCasting</strong></font><font color="#800000"><strong>Q?/strong></font></p> <p>使用<code>static_cast<>()</code>{C++的类型{换,不要使用<code>int y = (int)x</code>?code>int y = int(x);</code>?/p> <p><strong>定义Q?/strong>C++引入了有别于C的不同类型的cd转换操作?/p> <p><strong>优点Q?/strong>C语言的类型{换问题在于操作比较含p:有时是在做强制{换(?code>(int)3.5</code>Q,有时是在做类型{换(?code>(int)"hello"</code>Q。另外,C++的类型{换查找更Ҏ、更醒目?/p> <p><strong>~点Q?/strong>语法比较<font color="#800000">恶心QnastyQ?/font>?/p> <p><strong>l论Q?/strong>使用C++风格而不要用C风格cd转换?/p> <p>1) static_castQ和C风格转换怼可做值的强制转换Q或指针的父cd子类的明的向上转换Q?/p> <p>2) const_castQ移除const属性;</p> <p>3) reinterpret_castQ指针类型和整型或其他指针间不安全的怺转换Q仅在你Ҏ做一切了然于心时使用Q?/p> <p>4) dynamic_castQ除试外不要用,除单元测试外Q如果你需要在q行时确定类型信息,说明设计有缺P参?strong>RTTI</strong>Q?/p> <p><strong><font color="#800000">9. (Streams</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>只在记录日志时用流?/p> <p><strong>定义Q?/strong>是<code>printf()</code>?code>scanf()</code>的替代?/p> <p><strong>优点Q?/strong>有了,在输出时不需要关心对象的cdQ不用担心格式化字符串与参数列表不匹配(虽然在gcc中用printf也不存在q个问题Q,打开、关闭对应文件时Q流可以自动构造、析构?/p> <p><strong>~点Q?/strong>?code>pread()</code>{功能函数很难执行,如果不?code>printf</code>之类的函数而是使用很隑֯格式q行操作Q尤其是常用的格式字W串<code>%.*s</code>Q,不支持字符串操作符重新定序Q?code>%1s</code>Q,而这一点对国际化很有用?/p> <p><strong>l论Q?/strong></p> <p>不要使用,除非是日志接口需要,使用<code>printf</code>之类的代ѝ?/p> <p>使用还有很多利弊,代码一致性胜q一切,不要在代码中使用?/p> <p><strong>拓展讨论Q?/strong></p> <p>对这一条规则存在一些争论,q儿l出深层ơ原因。回?font color="#800000">唯一性原则(Only One WayQ?/font>Q我们希望在M时候都只用一U确定的I/OcdQ代码在所有I/O处保持一致。因此,我们不希望用h军_是用流q是<code>printf + read/write</code>Q我们应该决定到底用哪一U方式。把日志作ؓ例外是因为流非常适合q么做,也有一定的历史原因?/p> <p>的支持者们d是不二之选,但观点ƈ不是那么清晰有力Q他们所指出的所有优势也正是其劣势所在。流最大的优势是在输出时不需要关心输出对象的cdQ这是一个亮点,也是一个不I很容易用错类型,而编译器不会报警。用流时容易造成的一c错误是Q?/p><pre>cout << this; // Prints the address cout << *this; // Prints the contents</pre> <p></p> <p>~译器不会报错,因ؓ<<被重载,因一Ҏ们反对用操作符重蝲?/p> <p>有h?code>printf</code>的格式化丑陋不堪、易L差Q但也好不到哪儿去。看看下面两D代码吧Q哪个更加易读?</p><pre>cerr << "Error connecting to '" << foo->bar()->hostname.first << ":" << foo->bar()->hostname.second << ": " << strerror(errno); fprintf(stderr, "Error connecting to '%s:%u: %s", foo->bar()->hostname.first, foo->bar()->hostname.second, strerror(errno));</pre> <p></p> <p>你可能会_“把封装一下就会比较好了”,q儿可以Q其他地方呢Q而且不要忘了Q我们的目标是语言可能小Q而不是添加一些别人需要学习的新的内容?/p> <p>每一U方式都是各有利弊,“没有最好,只有更好”,单化的教条告诫我们必M中选择其一Q最后的多数军_?code>printf + read/write</code>?/p> <p><font color="#800000"><strong>10. 前置自增和自减(Preincrement and Predecrement</strong></font><font color="#800000"><strong>Q?/strong></font></p> <p>对于q代器和其他模板对象使用前缀形式Q?code>++i</code>Q的自增、自减运符?/p> <p><strong>定义</strong>Q对于变量在自增Q?code>++i</code>?code>i++</code>Q或自减Q?code>--i</code>?code>i--</code>Q后表达式的值又没有没用到的情况下,需要确定到底是使用前置q是后置的自增自减?/p> <p><strong>优点</strong>Q不考虑q回值的话,前置自增Q?code>++i</code>Q通常要比后置自增Q?code>i++</code>Q效率更高,因ؓ后置的自增自减需要对表达式的?code>i</code>q行一ơ拷贝,如果<code>i</code>是P代器或其他非数值类型,拯的代h比较大的。既然两U自增方式动作一P<font color="#800000">译者注Q不考虑表达式的|怿你知道我在说什?/font>Q,Z么不直接使用前置自增呢?</p> <p><strong>~点</strong>QC语言中,当表辑ּ的值没有用时Q传l的做法是用后|自增,特别是在<code>for</code>循环中,有些得后|自增更加易懂,因ؓq很像自然语aQ主语(<code>i</code>Q在谓语动词Q?code>++</code>Q前?/p> <p><strong>l论</strong>Q对单数|非对象)来说Q两U都无所谓,对P代器和模板类型来_要用前|自增(自减Q?/p> <p><strong><font color="#800000">11. const的用(Use of const</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>我们强烈你在M可以使用的情况下都要使用<code>const</code>?/p> <p><strong>定义</strong>Q在声明的变量或参数前加上关键字<code>const</code>用于指明变量g可修改(?code>const int foo</code>Q,为类中的函数加上<code>const</code>限定表明该函C会修改类成员变量的状态(?code>class Foo { int Bar(char c) const; };</code>Q?/p> <p><strong>优点</strong>Qh们更Ҏ理解变量是如何用的Q编辑器可以更好地进行类型检、更好地生成代码。h们对~写正确的代码更加自信,因ؓ他们知道所调用的函数被限定了能或不能修改变量倹{即使是在无锁的多线E编E中Qh们也知道什么样的函数是安全的?/p> <p><strong>~点</strong>Q如果你向一个函C?code>const</code>变量Q函数原型中也必L<code>const</code>的(否则变量需?code>const_cast</code>cd转换Q,在调用库函数时这其是个ȝ?/p> <p><strong>l论</strong>Q?code>const</code>变量、数据成员、函数和参数为编译时cd增加了一层保障,更好的尽早发现错误。因此,我们强烈在Q何可以用的情况下?code>const</code>Q?/p> <p>1) 如果函数不会修改传入的引用或指针cd的参敎ͼq样的参数应该ؓ<code>const</code>Q?/p> <p>2) 可能将函数声明?code>const</code>Q访问函数应该L<code>const</code>Q其他函数如果不会修改Q何数据成员也应该?code>const</code>Q不要调用非<code>const</code>函数Q不要返回对数据成员的非<code>const</code>指针或引用;</p> <p>3) 如果数据成员在对象构造之后不再改变,可将其定义ؓ<code>const</code>?/p> <p>然而,?strong>不要?code>const</code>q度使用</strong>Q像<code>const int * const * const x;</code>有些过了,即便q样写精描qC<code>x</code>Q其实写?code>const int** x</code>可以了?/p> <p>关键?code>mutable</code>可以使用Q但是在多线E中是不安全的,使用旉先要考虑U程安全?/p> <p><strong><code>const</code>位置</strong>Q?/p> <p>有h喜欢<code>int const *foo</code>形式不喜?code>const int* foo</code>Q他们认为前者更加一致因此可L更好:遵@?code>const</code>M于其描述的对象(<code>int</code>Q之后的原则。但是,一致性原则不适用于此Q“不要过度用”的权威抉|了一致性用。将<code>const</code>攑֜前面才更易读Q因为在自然语言中Ş容词Q?code>const</code>Q是在名词(<code>int</code>Q之前的?/p> <p>q是_我们提?code>const</code>在前Qƈ不是要求Q但要兼代码的一致性!</p> <p><font color="#800000"><strong>12. 整型QInteger Types</strong></font><font color="#800000"><strong>Q?/strong></font></p> <p>C++内徏整型中,唯一用到的是<code>int</code>Q如果程序中需要不同大的变量Q可以?code><stdint.h></code>中的<font color="#800000">_宽度Qprecise-widthQ?/font>的整型,?code>int16_t</code>?/p> <p><strong>定义</strong>QC++没有指定整型的大,通常Z认ؓ<code>short</code>?6位,<code>int</code>?2位,<code>long</code>?2位,<code>long long</code>?4位?/p> <p><strong>优点</strong>Q保持声明统一?/p> <p><strong>~点</strong>QC++中整型大因~译器和体系l构的不同而不同?/p> <p><strong>l论</strong>Q?/p> <p><code><stdint.h></code>定义?code>int16_t</code>?code>uint32_t</code>?code>int64_t</code>{整型,在需要确定大的整型时可以用它们代?code>short</code>?code>unsigned long long</code>{,在C整型中,只?code>int</code>。适当情况下,推荐使用标准cd?code>size_t</code>?code>ptrdiff_t</code>?/p> <p>最怋用的是,Ҏ数来_通常不会用到太大Q如循环计数{,可以使用普通的<code>int</code>。你可以认ؓ<code>int</code>臛_?2位,但不要认为它会多?2位,需?4位整型的话,可以使用<code>int64_t</code>?code>uint64_t</code>?/p> <p>对于大整敎ͼ使用<code>int64_t</code>?/p> <p>不要使用<code>uint32_t</code>{无W号整型Q除非你是在表示一?font color="#800000">位组Qbit patternQ?/font>而不是一个数倹{即使数g会ؓ负g不要使用无符L型,使用<font color="#800000">断言QassertionQ译者注Q这一点很有道理,计算机只会根据变量、返回值等有无W号定数值正负,仍然无法定寚wQ?/font>来保护数据?/p> <p><strong>无符h?/strong>Q?/p> <p>有些人,包括一些教U书作者,推荐使用无符L型表C非负数Q类型表明了数值取值Ş式。但是,在C语言中,q一优点被由其导致的bugs所Ҏ。看看:</p><pre>for (unsigned int i = foo.Length()-1; i >= 0; --i) ...</pre> <p></p> <p>上述代码永远不会l止Q有时gcc会发现该bugq报警,但通常不会。类似的bugq会出现在比较有W合变量和无W号变量Ӟ主要是C?font color="#800000">cd提升机制Qtype-promotion schemeQC语言中各U内建类型之间的提升转换关系Q?/font>会致使无W号cd的行为出乎你的意料?/p> <p>因此Q用断a声明变量为非负数Q不要用无W号型?/p> <p><font color="#800000"><strong>13. 64位下的可UL性(64-bit Portability</strong></font><font color="#800000"><strong>Q?/strong></font></p> <p>代码?4位和32位的pȝ中,原则上应该都比较友好Q尤其对于输出、比较?font color="#800000">l构寚wQstructure alignmentQ?/font>来说Q?/p> <p>1) <code>printf()</code>指定的一些类型在32位和64位系l上可移植性不是很好,C99标准定义了一些可UL的格式。不q的是,MSVC 7.1q全部支持Q而且标准中也有所遗漏。所以有时我们就不得不自己定义丑陋的版本Q用标准风D包含文g<code>inttypes.h</code>Q:</p><pre>// printf macros for size_t, in the style of inttypes.h #ifdef _LP64 #define __PRIS_PREFIX "z" #else #define __PRIS_PREFIX #endif // Use these macros after a % in a printf format string // to get correct 32/64 bit behavior, like this: // size_t size = records.size(); // printf("%"PRIuS"\n", size); #define PRIdS __PRIS_PREFIX "d" #define PRIxS __PRIS_PREFIX "x" #define PRIuS __PRIS_PREFIX "u" #define PRIXS __PRIS_PREFIX "X" #define PRIoS __PRIS_PREFIX "o" </pre> <p></p> <div align="center"> <table cellspacing="0" cellpadding="1" width="529" align="center" border="0"> <tbody> <tr> <td valign="top" width="154">cd</td> <td valign="top" width="109">不要使用</td> <td valign="top" width="142">使用</td> <td valign="top" width="122">备注</td></tr> <tr> <td valign="top" width="154"><code>void *</code>Q或其他指针cdQ?/td> <td valign="top" width="109"><code>%lx</code></td> <td valign="top" width="142"><code>%p</code></td> <td valign="top" width="122"> </td></tr> <tr> <td valign="top" width="154"><code>int64_t</code></td> <td valign="top" width="109"><code>%qd</code>, <code>%lld</code></td> <td valign="top" width="142"><code>%"PRId64"</code></td> <td valign="top" width="122"> </td></tr> <tr> <td valign="top" width="154"><code>uint64_t</code></td> <td valign="top" width="109"><code>%qu</code>, <code>%llu</code>, <code>%llx</code></td> <td valign="top" width="142"><code>%"PRIu64"</code>, <code>%"PRIx64"</code></td> <td valign="top" width="122"> </td></tr> <tr> <td valign="top" width="154"><code>size_t</code></td> <td valign="top" width="109"><code>%u</code></td> <td valign="top" width="142"><code>%"PRIuS"</code>, <code>%"PRIxS"</code></td> <td valign="top" width="122">C99指定<code>%zu</code></td></tr> <tr> <td valign="top" width="154"><code>ptrdiff_t</code></td> <td valign="top" width="109"><code>%d</code></td> <td valign="top" width="142"><code>%"PRIdS"</code></td> <td valign="top" width="122">C99指定<code>%zd</code></td></tr></tbody></table></div> <p><br>注意?code>PRI*</code>会被~译器扩展ؓ独立字符Ԍ因此如果使用非常量的格式化字W串Q需要将宏的D不是宏名插入格式中Q在使用?code>PRI*</code>时同样可以在<code>%</code>后指定长度等信息。例如,<code>printf("x = %30"PRIuS"\n", x)</code>?2位Linux上将被扩展ؓ<code>printf("x = %30" "u" "\n", x)</code>Q编译器会处理ؓ<code>printf("x = %30u\n", x)</code>?/p> <p>2) C<code>sizeof(void *)</code> != <code>sizeof(int)</code>Q如果需要一个指针大的整数要?code>intptr_t</code>?/p> <p>3) 需要对l构寚w加以留心Q尤其是对于存储在磁盘上的结构体。在64位系l中QQ何拥?code>int64_t</code>/<code>uint64_t</code>成员的类/l构体将默认被处理ؓ8字节寚w。如?2位和64位代码共用磁盘上的结构体Q需要确保两U体pȝ构下的结构体的对齐一致。大多数~译器提供了调整l构体对齐的Ҏ。gcc中可使用<code>__attribute__((packed))</code>QMSVC提供?code>#pragma pack()</code>?code>__declspec(align())</code><font color="#800000">Q译者注Q解x案的目属性里也可以直接设|)</font>?/p> <p>4) 创徏64位常量时使用<code>LL</code>?code>ULL</code>作ؓ后缀Q如Q?/p> <p><pre>int64_t my_value = 0x123456789LL; uint64_t my_mask = 3ULL << 48;</pre> <p></p> <p>5) 如果你确实需?2位和64位系l具有不同代码,可以在代码变量前使用。(量不要q么做,使用时尽量修改局部化Q?/p> <p><font color="#800000"><strong>14. 预处理宏QPreprocessor Macros</strong></font><font color="#800000"><strong>Q?/strong></font></p> <p>使用宏时要}慎,量以内联函数、枚丑֒帔R代替之?/p> <p>宏意味着你和~译器看到的代码是不同的Q因此可能导致异常行为,其是当宏存在于全局作用域中?/p> <p>值得庆幸的是QC++中,宏不像C中那么必要。宏内联<font color="#800000">效率关键代码Qperformance-critical codeQ?/font>可以内联函数替代Q宏存储帔R可以<code>const</code>变量替代Q宏“羃写”长变量名可以引用替代;使用宏进行条件编译,q个……,最好不要这么做Q会令测试更加痛苦(<code>#define</code>防止头文仉包含当然是个例外Q?/p> <p>宏可以做一些其他技术无法实现的事情Q在一些代码库Q尤其是底层库中Q可以看到宏的某些特性(?font color="#800000">字符串化QstringifyingQ译者注Q?code>#</code>Q?/font>?font color="#800000">q接QconcatenationQ译者注Q?code>##</code>Q?/font>{等Q。但在用前Q仔l考虑一下能不能不用宏实现同样效果?/p> <p><strong>译者注Q关于宏的高U应用,可以参?/strong><a title="C语言宏的高应用" target="_blank"><strong>C语言宏的高应用</strong></a><strong>?/strong></p> <p>下面l出的用法模式可以避免一些用宏的问题,供用宏时参考:</p> <p>1) 不要?code>.h</code>文g中定义宏Q?/p> <p>2) 使用前正?code>#define</code>Q用后正确<code>#undef</code>Q?/p> <p>3) 不要只是对已l存在的宏?code>#undef</code>Q选择一个不会冲H的名称Q?/p> <p>4) 不用会D不稳定的<font color="#800000">C++构造(unbalanced C++ constructsQ译者注Q?/font>的宏Q至文档说明其行ؓ?/p> <p><font color="#800000"><strong>15. 0和NULLQ? and NULL</strong></font><font color="#800000"><strong>Q?/strong></font></p> <p>整数?code>0</code>Q实数用<code>0.0</code>Q指针用<code>NULL</code>Q字W(Ԍ?code>'\0'</code>?/p> <p>整数?code>0</code>Q实数用<code>0.0</code>Q这一Ҏ毫无争议的?/p> <p>对于指针Q地址|Q到底是?code>0</code>q是<code>NULL</code>QBjarne Stroustrup使用最原始?code>0</code>Q我们徏议用看上去像是指针?code>NULL</code>Q事实上一些C++~译器(如gcc 4.1.0Q专门提供了<code>NULL</code>的定义,可以l出有用的警告,其?code>sizeof(NULL)?code>sizeof(0)</code>不相{?/code>的情c?/p> <p>字符Q串Q用<code>'\0'</code>Q不仅类型正而且可读性好?/p> <p><font color="#800000"><strong>16. sizeofQsizeof</strong></font><font color="#800000"><strong>Q?/strong></font></p> <p>可能用<code>sizeof(<var>varname</var>)</code>代替<code>sizeof(<var>type</var>)</code>?/p> <p>使用<code>sizeof(<var>varname</var>)</code>是因为当变量cd改变时代码自动同步,有些情况?code>sizeof(<var>type</var>)</code>或许有意义,q是要尽量避免,如果变量cd改变的话不能同步?/p><pre>Struct data; memset(&data, 0, sizeof(data));</pre><pre>memset(&data, 0, sizeof(Struct));</pre> <p></p> <p><font color="#800000"><strong>17. Boost库(Boost</strong></font><font color="#800000"><strong>Q?/strong></font></p> <p>只用Boost中被认可的库?/p> <p><strong>定义</strong>QBoost库集是一个非常受Ƣ迎的?font color="#800000">同评议的(peer-reviewedQ?/font>、免费的、开源的C++库?/p> <p><strong>优点</strong>QBoost代码质量普遍较高、可UL性好Q填补了C++标准库很多空白,?font color="#800000">型别Ҏ(type traitsQ?/font>、更完善?font color="#800000">l定QbindersQ?/font>、更好的指针Q同时还提供了TR1Q标准库的扩展)的实现?/p> <p><strong>~点</strong>Q某些Boost库提倡的~程实践可读性差Q像<font color="#800000">元程序(metaprogrammingQ?/font>和其他高U模板技术,以及q度<font color="#800000">“函数化”("functional"Q?/font>的编E风根{?/p> <p><strong>l论</strong>Qؓ了向阅读和维护代码的人员提供更好的可L,我们只允怋用BoostҎ的一个成熟子集,当前Q这些库包括Q?/p> <p>1) <a >Compressed Pair</a>Q?code>boost/compressed_pair.hpp</code>Q?/p> <p>2) <a >Pointer Container</a>Q?code>boost/ptr_container</code>不包?code>ptr_array.hpp</code>和序列化QserializationQ?/p> <p>我们会积极考虑d可以的BoostҎ,所以不必拘泥于该规则?/p> <p>______________________________________ </p> <p>译者:关于C++Ҏ的注意事项Qȝ一下: <p><strong>1. 对于指针Q安全第一、方便第二,可能局部化Qscoped_ptrQ?/strong><strong>Q?/strong> <p><strong>2. 引用形参加上constQ否则用指针Ş参;</strong> <p><strong>3. 函数重蝲的用要清晰、易读;</strong> <p><strong>4. 鉴于Ҏ误用Q禁止用缺省函数参敎ͼ值得商榷Q;</strong> <p><strong>5. 止使用变长数组Q?/strong> <p><strong>6. 合理使用友元Q?/strong> <p><strong>7. Z方便代码理Q禁止用异常(值得商榷Q;</strong> <p><strong>8. 止使用RTTIQ否则重新设计代码吧Q?/strong> <p><strong>9. 使用C++风格的类型{换,除单元测试外不要使用dynamic_castQ?/strong> <p><strong>10. 使用还printf + read/writeQit is a problemQ?/strong> <p><strong>11. 能用前置自增/减不用后|自?减;</strong> <p><strong>12. const能用则用Q提倡const在前Q?/strong></p> <p><strong>13. 使用定大小的整型,除位l外不要使用无符号型Q?/strong></p> <p><strong>14. 格式化输出及l构寚wӞ注意32位和64位的pȝ差异Q?/strong></p> <p><strong>15. 除字W串化、连接外量避免使用宏;</strong></p> <p><strong>16. 整数?Q实数用0.0Q指针用NULLQ字W(Ԍ?\0'Q?/strong></p> <p><strong>17. 用sizeof(varname)代替sizeof(type)Q?/strong></p> <p><strong>18. 只用Boost中被认可的库?/strong></p><img src ="http://www.shnenglu.com/Fox/aggbug/56760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-07-21 14:55 <a href="http://www.shnenglu.com/Fox/archive/2008/07/21/56760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>日志该怎么记录Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/07/18/56481.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Fri, 18 Jul 2008 02:03:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/07/18/56481.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/56481.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/07/18/56481.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/56481.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/56481.html</trackback:ping><description><![CDATA[<p>一个好的日志系l,除了可以记录可能多的必要信息,方便trace bugs、提供data analysis sourceq些基本功能之外Q其他的貌似不必太在意。但真正当bugs冒出来的时候,要命的是既没有dumpQ也没有有h值的日志Q更要命的是日志居然已经记录了那么多Q居然让你查了半天,居然都是没有价值的Q?/p> <p>悲剧啊!</p> <p>日志需要记录的信息大概分ؓ两类Q?/p> <p><strong>1) pȝq行情况</strong>Q启动、加载、读写、关闭?strong>异常</strong>Q?/p> <p><strong>2) 用户使用情况</strong>Q进入、操作、离开?strong>异常</strong>?/p> <p>我可以想到的关于日志pȝ的要求大致以下几点:</p> <p><strong>1) 日志pȝ使用目录树结?/strong>Q系l日志和用户日志分别记录Q正常日志和异常日志分别记录Q不|于同一文g夹下Q日志文件命名做Co观者一目了Ӟ</p> <p><strong>2) 记录详尽但不冗余</strong>Q正记录日志时间、位|、事件、因果,有可能的话,<strong>记录上下?/strong>Q这要求有点高了Q;</p> <p><strong>3) 格式l一但严千一?/strong>Q格式统一是指记录内容遵@一定格式,方便查看Q严千一律是指记录要有层ơ、轻重,不同事gD的“同一”异常日志不应不加区别,同样是ؓ了方便查看;</p> <p><strong>4) 与异常处理相辅相?/strong>Q有dumpӞ以日志辅助快速定位,没有dumpӞ日志应尽可能提供有效信息Q?strong>ȝl崩溃的地方近好</strong>Q这一点似乎也有难度)?/p> <p>________________________________________________</p> <p>H然惛_的,也还没有动手dQ先C了,Ƣ迎补充?/p> <p>_____Added on Jul.25th, 2008_______________________</p> <p>q看C位兄弟在为我说话Q谢谢!</p> <p>今天在考虑实现Ӟ惛_一个很现实的问题,日志几乎是无处不在的Q随旉C有日志记录。不知道有谁对I/OQ当然主要是OutputQ消耗和对系l的影响做过专门试Q猜就了:-)Q我很想知道有没有必要放C门的U程中,如果攑ֈ独立U程中的话,问题出来了Q多长时间写一ơ?毕竟Q记录日志的主要目的是Z全面记录pȝq行和用户用情况,如果在服务器crash的时候,q有日志Q尤其是crash上下文日志)没有被顺利写入,日志的意义也大打折扣?/p> <p>谁给点徏议?</p><img src ="http://www.shnenglu.com/Fox/aggbug/56481.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-07-18 10:03 <a href="http://www.shnenglu.com/Fox/archive/2008/07/18/56481.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[译]Google C++~程风格指南Q三Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/07/16/56324.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Wed, 16 Jul 2008 09:43:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/07/16/56324.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/56324.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/07/16/56324.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/56324.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/56324.html</trackback:ping><description><![CDATA[<p>q一主要提到的是类QLippman在?a title="Inside The C++ Object Model" href="www.amazon.com/Inside-Object-Model-Stanley-Lippman/dp/0201834545" target="_blank">Inside The C++ Object Model</a>》第二章中对构造函C了详说明,本文中提到的几个单词基本仿该书中译本侯捷先生的翻译:</p> <p>explicitQ明的</p> <p>implicitQ隐含的</p> <p>trivialQ没有意义的</p> <p>non-trivialQ有意义?/p> <p> </p> <p>原文地址Q?a title="Google C++ Style Guide" target="_blank" rel="tag">Google C++ Style Guide</a></p> <ul> <li><strong><font color="#800000">c?/font></strong></li></ul> <p>cLC++中基本的代码单元Q自然被q泛使用。本节列举了在写一个类时要做什么、不要做什么?/p> <p><strong><font color="#800000">1. 构造函敎ͼConstructorQ的职责</font></strong></p> <p>构造函C只进行那?font color="#800000">没有实际意义的(trivialQ译者注Q简单初始化对于E序执行没有实际的逻辑意义Q因为成员变量的“有意义”的值大多不在构造函C定Q?/font>初始化,可能的话Q用Init()Ҏ集中初始化ؓ<font color="#800000">有意义的Qnon-trivialQ?/font>数据?/p> <p><strong>定义Q?/strong>在构造函C执行初始化操作?/p> <p><strong>优点Q?/strong>排版方便Q无需担心cL否初始化?/p> <p><strong>~点Q?/strong>在构造函C执行操作引v的问题有Q?/p> <p>1) 构造函C不易报告错误Q不能用异常?/p> <p>2) 操作p|会造成对象初始化失败,引v不确定状态?/p> <p>3) 构造函数内调用虚函敎ͼ调用不会z֏到子cdCQ即使当前没有子cd实现Q将来仍是隐患?/p> <p>4) 如果有h创徏该类型的全局变量Q虽然违背了上节提到的规则)Q构造函数将在main()之前被调用,有可能破坏构造函C暗含的假设条件。例如,gflags未初始化?/p> <p><strong>l论Q?/strong>如果对象需?font color="#800000">有意义的Qnon-trivialQ?/font>初始化,考虑使用另外的Init()ҎqӞ或)增加一个成员标记用于指C对象是否已l初始化成功?/p> <p><strong><font color="#800000">2. 默认构造函敎ͼDefault ConstructorsQ?/font></strong></p> <p>如果一个类定义了若q成员变量又没有其他构造函敎ͼ需要定义一个默认构造函敎ͼ否则~译器将自动生默认构造函数?/p> <p><strong>定义Q?/strong>新徏一个没有参数的对象Ӟ默认构造函数被调用Q当调用new[]Qؓ数组Q时Q默认构造函数L被调用?/p> <p><strong>优点Q?/strong>默认结构体初始化ؓ“不可能的”|使调试更加容易?/p> <p><strong>~点Q?/strong>对代码编写者来_q是多余的工作?/p> <p><strong>l论Q?/strong></p> <p>如果cM定义了成员变量,没有提供其他构造函敎ͼ你需要定义一个默认构造函敎ͼ没有参数Q。默认构造函数更适合于初始化对象Q对象<font color="#800000">内部状态(internal stateQ?/font>一致、有效?/p> <p>提供默认构造函数的原因是:如果你没有提供其他构造函敎ͼ又没有定义默认构造函敎ͼ~译器将Z自动生成一个,~译器生成的构造函数ƈ不会对对象进行初始化? <p>如果你定义的cȝ承现有类Q而你又没有增加新的成员变量,则不需要ؓ新类定义默认构造函数? <p><strong><font color="#800000">3. 明确的构造函敎ͼExplicit ConstructorsQ?/font></strong></p> <p>对单参数构造函C用C++关键字explicit?/p> <p><strong>定义Q?/strong>通常Q只有一个参数的构造函数可被用?font color="#800000">转换QconversionQ译者注Q主要指隐式转换Q下文可见)</font>Q例如,定义了Foo::Foo(string name)Q当向需要传入一个Foo对象的函C入一个字W串Ӟ构造函数Foo::Foo(string name)被调用ƈ该字符串{换ؓ一个Foo临时对象传给调用函数。看上去很方便,但如果你q不希望如此通过转换生成一个新对象的话Q麻烦也随之而来。ؓ避免构造函数被调用造成隐式转换Q可以将其声明ؓexplicit?/p> <p><strong>优点Q?/strong>避免不合时宜的变换? <p><strong>~点Q?/strong>无? <p><strong>l论Q?/strong> <p>所有单参数构造函数必L明确的。在cd义中Q将关键字explicit加到单参数构造函数前Qexplicit Foo(string name); <p>例外Q在数情况下,拯构造函数可以不声明为explicitQ特意作为其他类的透明包装器的cR类g外情况应在注释中明确说明? <p><strong><font color="#800000">4. 拯构造函敎ͼCopy ConstructorsQ?/font></strong></p> <p>仅在代码中需要拷贝一个类对象的时候用拷贝构造函敎ͼ不需要拷贝时应?code>DISALLOW_COPY_AND_ASSIGN</code>?/p> <p><strong>定义Q?/strong>通过拯新徏对象时可使用拯构造函敎ͼ特别是对象的传值时Q?/p> <p><strong>优点Q?/strong>拯构造函C得拷贝对象更加容易,STL容器要求所有内容可拯、可赋倹{?/p> <p><strong>~点Q?/strong>C++中对象的隐式拯是导致很多性能问题和bugs的根源。拷贝构造函数降低了代码可读性,相比按引用传递,跟踪按g递的对象更加困难Q对象修改的地方变得难以捉摸?/p> <p><strong>l论Q?/strong></p> <p>大量的类q不需要可拯Q也不需要一个拷贝构造函数或<font color="#800000">赋值操作(assignment operatorQ?/font>。不q的是,如果你不d声明它们Q编译器会ؓ你自动生成,而且是public的?/p> <p>可以考虑在类的private中添?font color="#800000">I的QdummyQ?/font>拯构造函数和赋值操作,只有声明Q没有定义。由于这些空E序声明为privateQ当其他代码试图使用它们的时候,~译器将报错。ؓ了方便,可以使用宏DISALLOW_COPY_AND_ASSIGNQ?/p><code> <p>// 止使用拯构造函数和赋值操作的?br>// 应在cȝprivate:中?br>#define DISALLOW_COPY_AND_ASSIGN(TypeName) \<br>  TypeName(const TypeName&);               \<br>  void operator=(const TypeName&)</p> <p>class Foo {<br>public:<br>  Foo(int f);<br>  ~Foo(); <p>private:<br>  DISALLOW_COPY_AND_ASSIGN(Foo);<br>};</p></code> <p>如上所qͼl大多数情况下都应用DISALLOW_COPY_AND_ASSIGNQ如果类实需要可拯Q应在该cȝ头文件中说明原由Qƈ适当定义拯构造函数和赋值操作,注意在operator=中检?font color="#800000">自赋|self-assignmentQ?/font>情况?/p> <p>在将cM为STL容器值得时候,你可能有使类可拷贝的冲动。类似情况下Q真正该做的是用指针指向STL容器中的对象Q可以考虑使用std::tr1::shared_ptr?/p> <p><strong><font color="#800000">5. l构体和c(Structs vs. ClassesQ?/font></strong></p> <p>仅当只有数据时用structQ其它一概用class?/p> <p>在C++中,关键字struct和class几乎含义{同Q我们ؓ其h为添加语义,以便为定义的数据cd合理选择使用哪个关键字?/p> <p>struct被用在仅包含数据的消极对象(passive objectsQ上Q可能包括有兌的常量,但没有存取数据成员之外的函数功能Q而存取功能通过直接讉K实现而无需Ҏ调用Q这儿提到的Ҏ是指只用于处理数据成员的Q如构造函数、析构函数、Initialize()、Reset()、Validate()?/p> <p>如果需要更多的函数功能Qclass更适合Q如果不定的话Q直接用class?/p> <p>如果与STLl合Q对?font color="#800000">仿函敎ͼfunctorsQ和Ҏ(traitsQ?/font>可以不用class而是使用struct?/p> <p>注意Q类和结构体的成员变量用不同的命名规则?/p> <p><strong><font color="#800000">6. l承QInheritance</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>使用<font color="#800000">l合QcompositionQ译者注Q这一点也是GoF在《Design Patterns》里反复的)</font>通常比用承更适宜Q如果用承的话,只用公qѝ?/p> <p><strong>定义Q?/strong>当子cȝ承基cLQ子cd含了父基cL有数据及操作的定义。C++实践中,l承主要用于两种场合Q?font color="#800000">实现l承Qimplementation inheritanceQ?/font>Q子cȝ承父cȝ实现代码Q?font color="#800000">接口l承Qinterface inheritanceQ?/font>Q子cMl承父类的方法名U?/p> <p><strong>优点Q?/strong>实现l承通过原封不动的重用基cM码减了代码量。由于承是<font color="#800000">~译时声明(compile-time declarationQ?/font>Q编码者和~译器都可以理解相应操作q发现错误。接口承可用于E序上增强类的特定API的功能,在类没有定义API的必要实现时Q编译器同样可以侦错?/p> <p><strong>~点Q?/strong>对于实现l承Q由于实现子cȝ代码在父cd子类间g展,要理解其实现变得更加困难。子cM能重写父cȝ非虚函数Q当然也׃能修改其实现。基cM可能定义了一些数据成员,q要区分基类?font color="#800000">物理轮廓Qphysical layoutQ?/font>?/p> <p><strong>l论Q?/strong></p> <p>所有承必Lpublic的,如果想私有承的话,应该采取包含基类实例作ؓ成员的方式作为替代?</p> <p>不要q多使用实现l承Q组合通常更合适一些。努力做到只?font color="#800000">“是一个”("is-a"Q译者注Q其?has-a"情况下请使用l合Q?/font>的情况下使用l承Q如果Bar的确“是一U”FooQ才令Bar是Foo的子cR? <p>必要的话Qo析构函数为virtualQ必要是指,如果该类h虚函敎ͼ其析构函数应该ؓ虚函数? <p><strong>译者注Q至于子cL有额外数据成员,甚至父类也没有Q何数据成员的Ҏ情况下,析构函数的调用是否必要是语义争论Q从~程设计规范的角度看Q在含有虚函数的父类中,定义虚析构函数绝对必要?/strong> <p>限定仅在子类讉K的成员函CؓprotectedQ需要注意的是数据成员应始终为私有? <p>当重定义z的虚函数Ӟ在派生类中明声明其为virtual。根本原因:如果遗漏virtualQ阅读者需要检索类的所有祖先以定该函数是否ؓ虚函?font color="#800000">Q译者注Q虽然不影响其ؓ虚函数的本质Q?/font>? <p><strong><font color="#800000">7. 多重l承QMultiple Inheritance</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>真正需要用?font color="#800000">多重实现l承Qmultiple implementation inheritanceQ?/font>的时候非常少Q只有当最多一个基cM含有实现Q其他基c都是以<code>Interface</code>为后~的纯接口cL才会使用多重l承?/p> <p><strong>定义Q?/strong>多重l承允许子类拥有多个基类Q要作为纯接口的基cdh实现的基cd别开来?/p> <p><strong>优点Q?/strong>相比单承,多重实现l承可o你重用更多代码?/p> <p><strong>~点Q?/strong>真正需要用到多重实现承的时候非常少Q多重实现承看上去是不错的解决ҎQ通常可以扑ֈ更加明确、清晰的、不同的解决Ҏ?/p> <p><strong>l论Q?/strong>只有当所?font color="#800000">类QsuperclassQ?/font>除第一个外都是U接口时才能使用多重l承。ؓ保它们是纯接口Q这些类必须?code>Interface</code>为后~?/p> <p>注意Q关于此规则QWindows下有U例外情况(译者注Q将在本译文最后一的规则例外中阐qͼ?/p> <p><strong><font color="#800000">8. 接口QInterface</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>接口是指满特定条g的类Q这些类以Interface为后~Q非必需Q?/p> <p><strong>定义Q?/strong>当一个类满以下要求ӞUC为纯接口Q?/p> <p>1) 只有U虚函数Q?=0"Q和静态函敎ͼ下文提到的析构函数除外)Q?/p> <p>2) 没有非静态数据成员;</p> <p>3) 没有定义M构造函数。如果有Q也不含参数Qƈ且ؓprotectedQ?/p> <p>4) 如果是子c,也只能承满上q条件ƈ以Interface为后~的类?/p> <p>接口cM能被直接实例化,因ؓ它声明了U虚函数。ؓ保接口cȝ所有实现可被正销毁,必须Z声明虚析构函敎ͼ作ؓW?条规则的例外Q析构函C能是U虚函数Q。具体细节可参考Stroustrup的?a title="The C++ Programming Language, 3rd edition" href="www.amazon.com/Programming-Language-3rd-Bjarne-Stroustrup/dp/0201889544" target="_blank">The C++ Programming Language, 3rd edition</a>》第12.4节?/p> <p><strong>优点Q?/strong>以Interface为后~可o他h知道不能接口cd加实现函数或非静态数据成员,q一点对于多重承尤光要。另外,对于JavaE序员来_接口的概念已l深入h心?/p> <p><strong>~点Q?/strong>Interface后缀增加了类名长度,为阅d理解带来不便Q同Ӟ接口Ҏ作为实现细节不应暴露给客户?/p> <p><strong>l论Q?/strong>。只有在满上述需要时Q类才以Interfacel尾Q但反过来,满上述需要的cL必一定以Interfacel尾?/p> <p><strong><font color="#800000">9. 操作W重载(Operator Overloading</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>除少数特定环境外Q不要重载操作符?/p> <p><strong>定义Q?/strong>一个类可以定义诸如+?{操作符Q其可以像内徏cd一L接用?/p> <p><strong>优点Q?/strong>使代码看上去更加直观Q就像内建类型(如intQ那P重蝲操作W那些Equals()、Add(){黯淡无光的函数名好玩多了。ؓ了一些模板函数正工作,你可能需要定义操作符?/p> <p><strong>~点Q?/strong>虽然操作W重载o代码更加直观Q但也有一些不?/p> <p>1) h直觉Q让你误以ؓ一些耗时的操作像内徏操作那样dyQ?/p> <p>2) 查找重蝲操作W的调用处更加困难,查找Equals()昄比同{调?=Ҏ的多Q?/p> <p>3) 有的操作W可以对指针q行操作Q容易导致bugsQFoo + 4做的是一件事Q?amp;Foo + 4可能做的是完全不同的另一件事Q对于二者,~译器都不会报错Q其很难调试;</p> <p>4) 重蝲q有令你吃惊的副作用Q比如,重蝲操作W?amp;的类不能被前|声明?</p> <p><strong>l论Q?/strong></p> <p>一般不要重载操作符Q尤其是赋值操作(operator=Q比较阴险,应避免重载。如果需要的话,可以定义cMEquals()、CopyFrom(){函数?/p> <p>然而,极少数情况下需要重载操作符以便与模板或“标准”C++c衔接(如operator<<(ostream&, const T&)Q,如果被证明是正当的尚可接受,但你要尽可能避免q样做。尤其是不要仅仅Z在STL容器中作为key使用重载operator==或operator<Q取而代之,你应该在声明容器的时候,创徏相等判断和大比较的仿函数类型?/p> <p>有些STL法实需要重载operator==时可以这么做Q不要忘了提供文档说明原因?/p> <p>参?strong>拯构造函?/strong>?strong>函数重蝲</strong>?</p> <p><strong><font color="#800000">10. 存取控制QAccess Control</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>数据成员私有化Qƈ提供相关存取函数Q如定义变量foo_及取值函数foo()、赋值函数set_foo()?/p> <p>存取函数的定义一般内联在头文件中?/p> <p>参?strong>l承</strong>?strong>函数命名</strong>?/p> <p><strong><font color="#800000">11. 声明ơ序QDeclaration Order</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>在类中用特定的声明ơ序Qpublic:在private:之前Q成员函数在数据成员Q变量)前?/p> <p>定义ơ序如下Qpublic:、protected:、private:Q如果那一块没有,直接忽略卛_?/p> <p>每一块中Q声明次序一般如下:</p> <p>1) typedefs和enumsQ?/p> <p>2) 帔RQ?/p> <p>3) 构造函敎ͼ</p> <p>4) 析构函数Q?/p> <p>5) 成员函数Q含静态成员函敎ͼ</p> <p>6) 数据成员Q含静态数据成员?/p> <p>宏DISALLOW_COPY_AND_ASSIGN|于private:块之后,作ؓcȝ最后部分。参?strong>拯构造函?/strong>?/p> <p>.cc文g中函数的定义应尽可能和声明次序一致?/p> <p>不要大型函数内联到cȝ定义中,通常Q只有那些没有特别意义的或者性能要求高的Qƈ且是比较短小的函数才被定义ؓ内联函数。更多细节参?a title="[译]Google C++~程风格指南Q一Q? href="http://www.shnenglu.com/Fox/archive/2008/07/10/55818.html" target="_blank">译文W一的</a><strong>内联函数</strong>?/p> <p><strong><font color="#800000">12. ~写短小函数QWrite Short Functions</font></strong><strong><font color="#800000">Q?/font></strong></p> <p>們֐于选择短小、凝l的函数?/p> <p>长函数有时是恰当的,因此对于函数长度q没有严格限制。如果函数超q?0行,可以考虑在不影响E序l构的情况下其分割一下?/p> <p>即一个长函数现在工作的非常好Q一旦有人对其修改,有可能出现新的问题,甚至D难以发现的bugs。函数量短小、简单,便于他h阅读和修改代码?/p> <p>在处理代码时Q你可能会发现复杂的长函敎ͼ不要x修改现有代码:如果证实q些代码使用、调试困难,或者你需要用其中的一块Q考虑其分割为更加短、易于管理的若干函数?/p> <p>______________________________________ </p> <p>译者:关于cȝ注意事项Qȝ一下: <p><strong>1. 不在构造函C做太多逻辑相关的初始化Q?/strong> <p><strong>2. ~译器提供的默认构造函C会对变量q行初始化,如果定义了其他构造函敎ͼ~译器不再提供,需要编码者自行提供默认构造函敎ͼ</strong> <p><strong>3. 为避免隐式{换,需单参数构造函数声明ؓexplicitQ?/strong> <p><strong>4. 为避免拷贝构造函数、赋值操作的滥用和编译器自动生成Q可目前声明其ؓprivate且无需实现Q?/strong> <p><strong>5. 仅在作ؓ数据集合时用structQ?/strong> <p><strong>6. l合>实现l承>接口l承>U有l承Q子c重载的虚函C要声明virtual关键字,虽然~译器允怸q样做;</strong> <p><strong>7. 避免使用多重l承Q用时Q除一个基cd有实现外Q其他基cd为纯接口Q?/strong> <p><strong>8. 接口cȝ名以Interface为后~Q除提供带实现的虚析构函数、静态成员函数外Q其他均为纯虚函敎ͼ不定义非静态数据成员,不提供构造函敎ͼ提供的话Q声明ؓprotectedQ?/strong> <p><strong>9. 为降低复杂性,量不重载操作符Q模ѝ标准类中用时提供文档说明Q?/strong> <p><strong>10. 存取函数一般内联在头文件中Q?/strong> <p><strong>11. 声明ơ序Qpublic->protected->privateQ?/strong> <p><strong>12. 函数体尽量短、紧凑,功能单一?/strong></p><img src ="http://www.shnenglu.com/Fox/aggbug/56324.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-07-16 17:43 <a href="http://www.shnenglu.com/Fox/archive/2008/07/16/56324.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[译]Google C++~程风格指南Q二Q?/title><link>http://www.shnenglu.com/Fox/archive/2008/07/14/56109.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Mon, 14 Jul 2008 07:49:00 GMT</pubDate><guid>http://www.shnenglu.com/Fox/archive/2008/07/14/56109.html</guid><wfw:comment>http://www.shnenglu.com/Fox/comments/56109.html</wfw:comment><comments>http://www.shnenglu.com/Fox/archive/2008/07/14/56109.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/Fox/comments/commentRss/56109.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Fox/services/trackbacks/56109.html</trackback:ping><description><![CDATA[<p>原文地址Q?a title="Google C++ Style Guide" target="_blank" rel="tag">Google C++ Style Guide</a></p> <ul> <li><strong><font color="#800000">作用?/font></strong></li></ul> <p><strong><font color="#800000">1. 命名I间QNamespacesQ?/font></strong></p> <p>?cc文g中,提倡?font color="#800000">不具名的命名I间Qunnamed namespacesQ译者注Q不具名的命名空间就像不具名的类一Pg被介l的很少:-(Q?/font>。用具名命名空间时Q其名称可基于项目或路径名称Q不要用using指示W?/p> <p><strong>定义Q?/strong>命名I间全局作用域细分ؓ不同的、具名的作用域,可有效防止全局作用域的命名冲突?/p> <p><strong>优点Q?/strong>命名I间提供了(可嵌套)<font color="#800000">命名轴线Qname axisQ译者注</font><font color="#800000">Q将命名分割在不同命名空间内Q?/font>Q当ӞcM提供了(可嵌套)的命名uU(<font color="#800000">译者注Q将命名分割在不同类的作用域?/font>Q?/p> <p>举例来说Q两个不同项目的全局作用域都有一个类FooQ这样在~译或运行时造成冲突。如果每个项目将代码|于不同命名I间中,project1::Foo和project2::Foo作ؓ不同W号自然不会冲突?/p> <p><strong>~点Q?/strong>命名I间hqh性,因ؓ它们和类一h供了额外的(可嵌套的Q命名uUѝ在头文件中使用不具名的I间Ҏq背C++?font color="#800000">唯一定义原则QOne Definition Rule (ODR)Q?/font>?/p> <p><strong>l论Q?/strong>Ҏ下文要提到的策略合理用命名空间?/p> <p><strong><font color="#800000">1) 不具名命名空_Unnamed NamespacesQ?/font></strong></p> <p>?cc文g中,允许甚至提倡用不具名命名I间Q以避免q行时的命名冲突Q?/p> <p>namespace {                                   // .cc 文g? <p>// 命名I间的内Ҏ需~进<br>enum { UNUSED, EOF, ERROR };          // l常使用的符?br>bool AtEof() { return pos_ == EOF; }   // 使用本命名空间内的符号EOF <p>}  // namespace <p>然而,与特定类兌的文件作用域声明在该cM被声明ؓcd、静态数据成员或静态成员函敎ͼ而不是不具名命名I间的成员。像上文展示的那P不具名命名空间结束时用注?/ namespace标识? <p>不能?h文g中用不具名命名I间? <p><font color="#800000"><strong>2) 具名命名I间QNamed NamespacesQ?/strong></font> <p>具名命名I间使用方式如下Q?/p> <p>命名I间?font color="#800000">除文件包含、全局标识的声?定义以及cȝ前置声明?/font>的整个源文g装hQ以同其他命名空间相区分?/p> <p>// .h文g<br>namespace mynamespace { </p> <p>// 所有声明都|于命名I间?br>// 注意不要使用~进<br>class MyClass {<br>public:<br>  ...<br>  void Foo();<br>}; <p>}  // namespace mynamespace</p> <p>// .cc文g<br>namespace mynamespace { </p> <p>// 函数定义都置于命名空间中<br>void MyClass::Foo() {<br>  ...<br>} <p>}  // namespace mynamespace <p>通常?cc文g会包含更多、更复杂的细节,包括对其他命名空间中cȝ引用{? <p>#include "a.h" <p>DEFINE_bool(someflag, false, "dummy flag"); <p>class C;  // 全局命名I间中类C的前|声?br>namespace a { class A; }  // 命名I间a中的ca::A的前|声? <p>namespace b { <p>...code for b...                // b中的代码 <p>}  // namespace b</p> <p>不要声明命名I间std下的M内容Q包括标准库cȝ前置声明。声明std下的实体会导致不明确的行为,如,不可UL。声明标准库下的实体Q需要包含对应的头文件?/p> <p>最好不要用using指示W,以保证命名空间下的所有名U都可以正常使用?/p> <p>// 止——污染命名空?br>using namespace foo;</p> <p>?cc文g?h文g的函数、方法或cMQ可以用using?/p> <p>// 允许Q?cc文g?br>// .h文g中,必须在函数、方法或cȝ内部使用<br>using ::foo::bar;</p> <p>?cc文g?h文g的函数、方法或cMQ还可以使用命名I间别名?/p>// 允许Q?cc文g?br>// .h文g中,必须在函数、方法或cȝ内部使用<br> <p>namespace fbz = ::foo::bar::baz;</p> <p><strong><font color="#800000">2. 嵌套c(Nested ClassQ?/font></strong></p> <p>当公开嵌套cM为接口的一部分Ӟ虽然可以直接他们保持在全局作用域中Q但嵌套类的声明置于命名空间中是更好的选择?/p> <p><strong>定义Q?/strong>可以在一个类中定义另一个类Q嵌套类也称<font color="#800000">成员c(member classQ?/font>? <p>class Foo { <p>private:<br>  // Bar是嵌套在Foo中的成员c?br>  class Bar {<br>    ...<br>  }; <p>}; <p><strong>优点Q?/strong>当嵌套(成员Q类只在<font color="#800000">被嵌套类Qenclosing classQ?/font>中用时很有用,其|于被嵌套类作用域作嵌套cȝ成员不会污染其他作用域同名类。可在被嵌套cM前置声明嵌套c,?cc文g中定义嵌套类Q避免在被嵌套类中包含嵌套类的定义,因ؓ嵌套cȝ定义通常只与实现相关? <p><strong>~点Q?/strong>只能在被嵌套cȝ定义中才能前|声明嵌套类。因此,M使用Foo::Bar*指针的头文g必须包含整个Foo的声明? <p><strong>l论Q?/strong>不要嵌套类定义为publicQ除非它们是接口的一部分Q比如,某个Ҏ使用了这个类的一pd选项? <p><font color="#800000"><strong>3. 非成员函敎ͼNonmemberQ、静态成员函敎ͼStatic MemberQ和全局函数QGlobal FunctionsQ?/strong></font> <p>使用命名I间中的非成员函数或静态成员函敎ͼ量不要使用全局函数? <p><strong>优点Q?/strong>某些情况下,非成员函数和静态成员函数是非常有用的,非成员函数|于命名I间中可避免对全局作用域的污染? <p><strong>~点Q?/strong>非成员函数和静态成员函C为新cȝ成员或许更有意义Q当它们需要访问外部资源或h重要依赖时更是如此? <p><strong>l论Q?/strong> <p>有时Q不把函数限定在cȝ实体中是有益的,甚至需要这么做Q要么作为静态成员,要么作ؓ非成员函数。非成员函数不应依赖于外部变量,q尽量置于某个命名空间中。相比单Uؓ了封装若q不׃nM静态数据的静态成员函数而创建类Q不如用命名空间? <p>定义于同一~译单元的函敎ͼ被其他编译单元直接调用可能会引入不必要的耦合和连接依赖;静态成员函数对此尤其敏感。可以考虑提取到新cMQ或者将函数|于独立库的命名I间中? <p>如果你确实需要定义非成员函数Q又只是?cc文g中用它Q可使用不具名命名空间或static兌Q如<code>static int Foo() {...}</code>Q限定其作用域? <p><strong><font color="#800000">4. 局部变量(Local VariablesQ?/font></strong> <p>函数变量尽可能|于最作用域内,在声明变量时其初始化?/p> <p>C++允许在函数的M位置声明变量。我们提倡在可能小的作用域中声明变量,ȝ一ơ用越q越好。这使得代码易于阅读Q易于定位变量的声明位置、变量类型和初始倹{特别是Q应使用初始化代替声?赋值的方式?/p> <p>int i;<br>i = f();        // 坏——初始化和声明分?br>nt j = g();   // 好——初始化时声?/p> <p>注意Qgcc可正执行for (int i = 0; i < 10; ++i)Qi的作用域仅限for循环Q,因此其他for循环中可重用i。if和while{语句中Q?font color="#800000">作用域声明(scope declarationQ?/font>同样是正的?/p> <p>while (const char* p = strchr(str, '/')) str = p + 1;</p> <p>注意Q如果变量是一个对象,每次q入作用域都要调用其构造函敎ͼ每次退Z用域都要调用其析构函数?/p> <p>// 低效的实?br>for (int i = 0; i < 1000000; ++i) {<br>  Foo f;  // 构造函数和析构函数分别调用1000000ơ!<br>  f.DoSomething(i);<br>}</p> <p>cM变量攑ֈ循环作用域外面声明要高效的多Q?/p> <p>Foo f;  // 构造函数和析构函数只调??br>for (int i = 0; i < 1000000; ++i) {<br>  f.DoSomething(i);<br>}</p> <p><strong><font color="#800000">5. 全局变量QGlobal VariablesQ?/font></strong></p> <p>classcd的全局变量是被止的,内徏cd的全局变量是允许的Q当然多U程代码中非常数全局变量也是被禁止的。永q不要用函数返回值初始化全局变量?/p> <p>不幸的是Q全局变量的构造函数、析构函C及初始化操作的调用顺序只是被部分规定Q每ơ生成有可能会有变化Q从而导致难以发现的bugs?/p> <p>因此Q禁止用classcd的全局变量Q包括STL的string, vector{等Q,因ؓ它们的初始化序有可能导致构造出现问题。内建类型和由内建类型构成的没有构造函数的l构体可以用,如果你一定要使用classcd的全局变量Q请使用<font color="#800000">单g模式Qsingleton patternQ?/font>?/p> <p>对于全局的字W串帔RQ用C风格的字W串Q而不要用STL的字W串Q?/p> <p>const char kFrogSays[] = "ribbet";</p> <p>虽然允许在全局作用域中使用全局变量Q用时务必三思。大多数全局变量应该是类的静态数据成员,或者当其只?cc文g中用时Q将其定义到不具名命名空间中Q或者用静态关联以限制变量的作用域?/p> <p>CQ静态成员变量视作全局变量Q所以,也不能是classcdQ?/p> <p>______________________________________ </p> <p>译者:q一主要提到的是作用域的一些规则,ȝ一下: <p><strong>1. .cc中的不具名命名空间可避免命名冲突、限定作用域Q避免直接用using提示W污染命名空_</strong> <p><strong>2. 嵌套cȝ合局部用原则,只是不能在其他头文g中前|声明,量不要publicQ?/strong> <p><strong>3. 量不用全局函数和全局变量Q考虑作用域和命名I间限制Q尽量单独Ş成编译单元;</strong> <p><strong>4. 多线E中的全局变量Q含静态成员变量)不要使用classcdQ含STL容器Q,避免不明行为导致的bugs</strong><strong>?/strong> <p><strong>作用域的使用Q除了考虑名称污染、可L之外,主要是ؓ降低耦合度,提高~译、执行效率?/strong></p><img src ="http://www.shnenglu.com/Fox/aggbug/56109.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Fox/" target="_blank">Fox</a> 2008-07-14 15:49 <a href="http://www.shnenglu.com/Fox/archive/2008/07/14/56109.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.steelcom.cn" target="_blank">պ뾫Ʒþһ </a>| <a href="http://www.lcvy.cn" target="_blank">鶹Ʒþþþþþ99</a>| <a href="http://www.gofiv.cn" target="_blank">þZYZԴվĶ</a>| <a href="http://www.kanqiuwang.cn" target="_blank">ĻƷþ</a>| <a href="http://www.zjzlgs.cn" target="_blank">þþþùһëƬ</a>| <a href="http://www.eurocake.com.cn" target="_blank">޹Ʒþþþվ</a>| <a href="http://www.tmuseum.cn" target="_blank">þþƷav鶹С˵ </a>| <a href="http://www.nutiao.cn" target="_blank">þþѹ۳ӰԺ </a>| <a href="http://www.idhm.cn" target="_blank">þˬˬƬAV</a>| <a href="http://www.ccbscc.com.cn" target="_blank">þ91Ʒ91þû</a>| <a href="http://www.more1.cn" target="_blank">Ʒ99þþƷ</a>| <a href="http://www.bisibbs.cn" target="_blank">þù޾Ʒ鶹</a>| <a href="http://www.020xyk.cn" target="_blank">99Ʒþþþþþó</a>| <a href="http://www.99j9.cn" target="_blank">97þۺɫۺɫhd</a>| <a href="http://www.hmnykj.cn" target="_blank">þþþþۺһĻ</a>| <a href="http://www.zgcl.org.cn" target="_blank">ƷþþþӰԺ۲</a>| <a href="http://www.hgndg.cn" target="_blank">˾þô߽槼 </a>| <a href="http://www.bisibbs.cn" target="_blank">þþƷ޾Ʒŷ</a>| <a href="http://www.wvzw.cn" target="_blank">þþþùƷ鶹ARӰԺ</a>| <a href="http://www.acesolo.cn" target="_blank">ŷҹͽþþ </a>| <a href="http://www.juzijia.cn" target="_blank">þþƷ</a>| <a href="http://www.uushipin.cn" target="_blank">˺ݺۺϾþ</a>| <a href="http://www.hkzkzs.com.cn" target="_blank">˾þ</a>| <a href="http://www.http321.cn" target="_blank">þô̫㽶av</a>| <a href="http://www.manour.cn" target="_blank">Ʒþþþþ</a>| <a href="http://www.cqhxdj.com.cn" target="_blank">Ըߺþþþþþþ</a>| <a href="http://www.dykh-tech.cn" target="_blank">þõӰһ</a>| <a href="http://www.zqfhsb8.cn" target="_blank">þ¶Ʒ</a>| <a href="http://www.21chem.cn" target="_blank">69Ʒþþþ9999APGF</a>| <a href="http://www.cu76.cn" target="_blank">2021þùԲľƷ</a>| <a href="http://www.aboto.cn" target="_blank">þӰԺþ㽶߿ۿ</a>| <a href="http://www.dygdgs.cn" target="_blank">69Ʒþþþùۿ </a>| <a href="http://www.salhm.cn" target="_blank">ξþ99Ʒþþþþ</a>| <a href="http://www.gangzheng.net.cn" target="_blank">ھƷþۺ88</a>| <a href="http://www.51s8s.cn" target="_blank">2021ƷۺϾþ</a>| <a href="http://www.2046film.cn" target="_blank">þ99ۺϾƷҳ</a>| <a href="http://www.wushuichulisb.cn" target="_blank">þþƷۺ</a>| <a href="http://www.nokia-flash.cn" target="_blank">һþ</a>| <a href="http://www.liaoningluntan.cn" target="_blank">ҹƷþþĸ</a>| <a href="http://www.e-zhishi.cn" target="_blank">þþƷAAƬһ</a>| <a href="http://www.ivgh.cn" target="_blank">ƷƵþþþ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>