最近公司对编码风格进行总结,也学到了不少东西。

Windows代码

如果你一直在windows平台下编码,这儿有必要强调一下下面的规则:

1) 不要使用匈牙利命名法,正如你没有必要将循环控制变量i写成iI或者iLoopControl一样,而且很显然的,匈牙利命名法完全不适用C++模版,任何试图通过变量前缀来区分map<string, string>和map<string, int>的想法都是很折磨人的;

    感觉完全遵守匈牙利命名法很累人的(想想VC里面可怕的变量名,苍天呀),尤其是临时的函数内的局部变量。但是如果类的成员,用m_iXX,m_strXXX来修饰下视觉上还是比较美观的。尤其是对于全局变量用g_XXX也很清晰。

2) Windows系统定义了很多原有内建类型的同义词,如DWORDHANDLE等等,在调用Windows API时这是完全可以接受甚至鼓励的,但在其它情况下还是尽量使用原来的C++类型,例如,使用const TCHAR *而不是LPCTSTR

    更喜欢用简单的名称LPCTSTR明显比const TCHAR *写起来方便,但是移植可能很不方便。

3) 不要使用#pragma once;放在头文件里面作为包含保护,使用C和C++标准的包含保护(注:#ifndef ...)

   从来没有用过#pragma once - -

4) 除非万不得已,否则不使用任何不标准的扩展,如#pragma__declspec,允许使用__declspec(dllimport)__declspec(dllexport),但必须通过DLLIMPORTDLLEXPORT等宏定义,以便其他人在共享使用这些代码时容易放弃这些扩展。

    都是微软VC自动生存DLL工程的,接口都写在def文件里了,这些基本没有用过 - -


头文件:

通常,每一个.c(C的源文件)和.cpp文件(C++的源文件)都有一个对应的.h文件(头文件),也有一些例外,如单元测试代码和只包含main()的体积较小的源文件。

正确使用头文件可令代码在可读性、文件大小和性能上大为改观。

一个.cpp对于一个.h,我一般一个类写在一对hpp文件里面,但有时候某个类的成员特别大,功能特别多,就分成多个.cpp和1个.h。在Source Insight里面看起来比较舒服,也不会把.cpp文件变的特别长


避免头文件被重复包含

所有头文件都应该使用#define防止头文件被重复包含,为保证唯一性,头文件的命名应基于其所在项目源代码树的全路径。例如,项目foo中的头文件foo/src/bar/baz.h按如下方式保护:

#ifndef __FOO_BAR_BAZ_H__

#define __FOO_BAR_BAZ_H__

...

#endif // __FOO_BAR_BAZ_H__

没什么意见,不是很喜欢使用路径,更喜欢使用该文件的作用来作为宏定义。



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

好乱,感觉不会写了,还是写写以前不知道或者没注意的东西吧。

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

/*b.h*/

class b

{

a _a;

};

/*a.h*/

class a

{

}

---------

那么b.h可以编译过去吗?(b.h里没有include "a.h")

如果又其他一个文件调用b时,同时include "a.h",include "b.h",那么就一切OK,头文件的读取是次序的,所以顺利编译通过。




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


命名空间:

是用using name std好,还是每个都用上std::前缀好呢?std::string,std::list


公司里问一圈,除了喜欢用boost的,都很懒很懒的时候用第一种。

当然,我也是懒人之一,呵呵。


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


static加变量是什么意思(学过C的都知道吧,毕竟任何一本书都会提到)

static加类成员是变成全局函数。

那么static加非成员函数有什么用?


函数默认都是全局的,加上static那么,就变成只有本文件才能使用了。



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


class类型全局变量,如果有多个,而构造函数依赖另外一个,那么可能会有问题。

因为这种变量,先构造哪一个是不能控制的。

就算只有一个如果用了STD的string,list也有问题,因为你无法确认他们的创建没有关系。


我写代码的时候,一般就起一个class类型的全局变量来放置配置信息,成员变量都用基本类型,用全局指针,总是感觉不放心。


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


构造函数中,直接return;不会造成创建失败,也就是new仍然返回值。

目前而言,没有办法让new返回NULL。

而且我们老大说了个我一直不知道的事情,现在C++ new失败是抛异常!而不是返回空

另外2位大佬献身说明,捕获了异常也没用,程序肯定崩溃,因为new失败,不是说明没有内存了(因为可以写磁盘),而是没有地址空间了!捕获了异常也是程序崩溃。说明程序有问题!


所以也就说,从此我们写代码不用判断new失败的情况了,耶!不用if(NULL=XX)或者if(!XX)


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


就算没有写无参数的构造函数,系统也没有给你生成一个。

也就是说,你们没有无参数的构造函数,但是你new C()依然成功。当然内部处理肯定出错了。


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


显式的构造函数:

Foo::Foo(string name)//构造函数

那么某个函数以这个类为参数 foo2(Foo),你直接将string变量传递进去,一样OK!自动帮你生存Foo的实例。



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


struct没有成员函数,但可以用指向函数的指针实现。   
比如:   
struct   test{   
int   a;   
int   (*add)();//当函数指针指向不同的函数可以实现对不同的操作   
};   
int   addd(int   a)   
{   
          return   ++a;   
}   
    
main()   
{   
          int   i;   
          struct   test   t;   
          t.a=1;   
            t.add=addd;   
          printf("%d\n",i=t.add(t.a));   
          return   0;   
}



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


友元用来做单元测试比较好


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



windows里面的流竟然不支持64位整形,还是老老实实用printf吧。



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


对迭代器和模板类型来说,要使用++i,而不要用i++。

因为i++需要对原来的表达式的值进行一次拷贝,当然如果是基本类型当然无所谓


随便提一下,在for循环里便利map,erase掉自己需要的,最好不要把i++写到for括号里。

for(i!=map.end;)

{

if(...)

map.erase(i++);

else

++i;

}


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


对于常数还是define宏定义的好,因为可以写头文件里随便用,但是const定义的常量只能给被文件用,用extern也没用,取不到值。


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



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