惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
O
OpenAI News
V
Vulnerabilities – Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
S
Schneier on Security
Latest news
Latest news
F
Full Disclosure
T
Tenable Blog
T
Troy Hunt's Blog
The Last Watchdog
The Last Watchdog
S
Secure Thoughts
L
LangChain Blog
有赞技术团队
有赞技术团队
Project Zero
Project Zero
Cloudbric
Cloudbric
爱范儿
爱范儿
GbyAI
GbyAI
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
The Exploit Database - CXSecurity.com
S
Security @ Cisco Blogs
Hugging Face - Blog
Hugging Face - Blog
Recorded Future
Recorded Future
大猫的无限游戏
大猫的无限游戏
Last Week in AI
Last Week in AI
C
Cisco Blogs
WordPress大学
WordPress大学
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V2EX - 技术
V2EX - 技术
Engineering at Meta
Engineering at Meta
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Hacker News: Ask HN
Hacker News: Ask HN
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Schneier on Security
Schneier on Security
T
Threat Research - Cisco Blogs
M
MIT News - Artificial intelligence
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
K
Kaspersky official blog
The Hacker News
The Hacker News
V
V2EX
F
Fortinet All Blogs
L
LINUX DO - 最新话题
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News | PayPal Newsroom
博客园 - 三生石上(FineUI控件)
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org

博客园 - CoderZh

[公告]这里的博客将不再更新,最新博客请移步至blog.coderzh.com 使用ThreadSanitizer线程检查工具 使用Jekyll官方的ReadMore摘要功能 小记:《技术进步引发的灵感革命》网易游戏学院第二届公开日 强制链接静态库所有符号(包括未被使用的) 开启Github之旅 Cocos2d-x3.6 Android编译问题 读《程序员的思维训练》 最近的一些变化 成大事者不纠结 读《从0到1》 OpenWrt资料汇总 C++开源代码覆盖率工具OpenCppCoverage介绍(Windows) Facebook网络模拟测试工具ATC使用 为什么心跳包(HeartBeat)是必须的? DigitalOcean上使用Tornado+MongoDB+Nginx+Supervisor+DnsPod快速搭建个人博客 创业三年来的一些感想 - 创业篇1 创业三年来的一些感想 - 游戏篇 ViEmuVS2013-3.2.1 破解
从CEGUI源码看代码规范
CoderZh · 2011-05-08 · via 博客园 - CoderZh

CEGUI(Crazy Eddie’s GUI)是一个使用C++实现的基于LGPL协议的的开源GUI库,主要应用于游戏界面。连著名的开源游戏引擎Orge3D也放弃了自己的界面引擎而使用第三方的开源界面引擎CEGUI。

对于开源的代码工程,我首先会观察它的代码规范。比如,使用什么命名法,是否使用异常等等,这很有用。看不同的开源工程,可以看到各种不同的代码规范,其中有很多是值得借鉴的。

代码规范本身并没有绝对的对错之分,但我们往往为了某一个代码规范争论的面红耳赤。比如,是否使用匈牙利命名法,使用BOOL还是bool等等。这时,就必须综合考虑团队现有的使用习惯和既有代码的风格,制定出一套适合自己的统一的规范。所以,规范除了对与错,最关键的地方还是要统一。存在即合理,我们不要一味去排斥其他人的使用习惯和规范,而应该多读读别人的代码,看看著名的开源代码,了解别人的做法,然后对自己的做法进行一些反思。这才是面对代码规范正确的心态。

CEGUI是一套不错的界面库,界面布局使用XML来描述,提供了专用的界面编辑器,让界面制作变得更简单。CEGUI作为一个成熟的开源产品,代码已经经历了无数的千锤百炼,整体风格比较统一,是一个很好的学习范本。接下来,我粗浅的分析一下CEGUI一些值得学习的地方。

1. Camel命名法

CEGUI完全摈弃了匈牙利命名法,而使用更贴近语义的不使用变量类型前缀的Camel(骆驼)命名法,这也是现今代码通用的做法。匈牙利命名法在较老的工程中比较常见。无数使用Camel的著名开源工程,很好的告诉了匈牙利命名法的支持者,不使用匈牙利命名法,代码依然清晰可读,甚至会更好。

2. 成员变量前缀

CEGUI中无论是class还是struct,成员变量都统一加d_前缀。通常的两种做法是不加前缀和加m_前缀。

3. struct

CEGUI中,struct的命名没有使用全大写,而是和class的大小写命名一样。在struct中,只可能出现数据成员,操作符重载函数,构造函数等。struct只用来数据结构存储使用,不使用任何其他的成员函数。

4. 字符串处理

CEGUI中的字符串处理没有使用char, wchar_t, TCHAR,std:string,ATL::CString,而是自己实现了一套String类(CEGUIString.h)。自己实现的String类优势非常明显,可以让程序员从繁琐的字符指针操作中解脱出来,将更多的精力放在功能的实现上。自定义的String可以实现更多方便、切合实际使用的函数。(比如CEGUI中的find_first_not_of,replace等函数。)如果要实现一个String类,CEGUI中的CEGUIString是一个很好的范本。

5. 使用bool

使用bool和BOOL都有各自的理由,CEGUI中全部使用bool,是现在流行,最常见的,也是我喜欢的做法。

6. 异常机制

CEGUI中完全使用异常机制,通过重载std::exception定义了一套完整的异常机制。通过异常的处理,使得程序员从繁琐的错误检查和错误返回值中解放出来。如果想了解C++中如何能够很好的使用异常,看看CEGUI中异常的实现吧(CEGUIExceptions.h)。

7. 不用goto

几乎每一本教材都会告诫用户,不要使用goto,这会让你的代码变得凌乱不堪。然而当真正成为一个程序员,加入一个公司甚至大型公司,里面的代码照样充斥了无数的goto语句。goto的滥用是绝对不允许的,goto在某些情况下的确有它的合理之处(比如保证函数单一出口,释放资源)。还是那句话,存在即合理。CEGUI中完全不使用goto,有了错误,立即抛异常,或者直接返回。我本人也是比较喜欢这种提前返回的方式。

8. 简单易用的Log系统

如果想实现一个既简单,又易用的Log系统,就看看CEGUI中的实现吧(CEGUILogger)。支持Log等级(Error,Warning等),输出日期、当前代码行等功能。

9. Singleton的实现

CEGUI中使用了一个通用的Singleton<T>模板基类,这个技巧非常好使。实现也非常简单:

template <typename T> class CEGUIEXPORT Singleton
{
protected:
    
static
#ifdef __MINGW32__
    CEGUIEXPORT
#endif
    T
* ms_Singleton;
public:
    Singleton( 
void )
    {
        assert( 
!ms_Singleton );
        ms_Singleton 
= static_cast<T*>(this);
    }
   
~Singleton( void )
        {  assert( ms_Singleton );  ms_Singleton 
= 0;  }
    
static T& getSingleton( void )
        {  assert( ms_Singleton );  
return ( *ms_Singleton );  }
    
static T* getSingletonPtr( void )
        {  
return ( ms_Singleton );  }
private:
    Singleton
& operator=(const Singleton&) { return this; }
    Singleton(
const Singleton&) {}
};


如上面的Logger类,要使用Singleton,则这样定义:

class CEGUIEXPORT Logger : public Singleton <Logger>
{
}

这样做最大的一个好处是统一,不会在代码中出现各种稀奇古怪不同的Singleton实现。同时哪个class是Singleton也一目了然。

总结   

本文仅仅讨论CEGUI中的代码规范,而且也只是其中很小的一部分,如有疏漏欢迎一起讨论。之后我会更加关注CEGUI现细节,如有收获将与大家分享。
最后,我还是那句话:不要完全排斥任何一种规范,将每种规范了解和使用过后,再来思考自己应该怎样做。

CEGUI主页:http://www.cegui.org.uk

源码下载 :http://www.cegui.org.uk/wiki/index.php/Downloads