VC的编码规范,现在应该有很多版本了。我想,规范只是一种普遍的要求。比如法律,道德观。虽多但不一定全。大家在编程中肯定会有一些自己的风格。希望大家在本贴中发表一下自己在编程中喜欢的风格。
另外,在面向对象这个前提下,我们应该如何来开发VC项目。包括可行的经验,和不可行的经验。希望大家踊跃发言。
相信我们的成功或者失败的经验都能给后来者以启发。
另外,在面向对象这个前提下,我们应该如何来开发VC项目。包括可行的经验,和不可行的经验。希望大家踊跃发言。
相信我们的成功或者失败的经验都能给后来者以启发。
解决方案 »
- BHO和MFC的对话程序能进行交互吗?
- COM 和 ActiveX 如何入门
- 期待高手们帮忙:一个消息传递的问题
- 分享:又是这个OwnerDraw折腾了半天,k!
- 在自己做的VIEW上“飘”非模态对话框--类似于Word上的“查找与替换”--出现一些Release版本的问题
- 将一个工程从系统盘是C盘的系统,放到系统盘是D盘的系统是要注意哪些问题,一般要在工程中改哪些部分?
- 为什么文件会打不开?
- MFC项目已经完成后,如何只改变项目名称和各个源文件的名称.
- 编译时提示VC的源代码错误 olectl.h
- 请问:BIOS 在CMOS 中是如何存储口令的?如何读出?
- 求VC++6.0的安装
- 谁知道用SHELL调用KV2004时,传什么参数给KV2004,让它自动杀毒吗?
我喜欢所有单纯的set和get都inline,喜欢每个类生成时都去掉VC自动生成的virtual destructor,除非自己认为一定有virtual的必要。喜欢使用STL的container而不是MFC的container。
使用STL container时喜欢使用指针。其实就我现在开发的这几个不算太大的项目,只要自己的逻辑完备,这么用也未尝不可,且效率高。
请大家多批评。
1、使用自定义的宏,完成一定的注释或其他的功能!
2、定义变量:
一般在函数的开头定义,定义后注明变量的用意。
3、函数的定义:
类型函数名各占取一行,类似:
VOID MyFunction(int iCount)
定义时使用:
VOID
MyFunction(
int iCount)
{
......
}
4、局部变量不加前缀,比如:
BOOL bHide = FALSE;
5、全局的一般加入一个前缀g_,比如:
BOOL g_bMaterail = FALSE;
6、一般命名原则遵循匈牙利命名原则。
函数的说明格式如下:
///////////////////////////////////////////////////
// ------------------------------------------------
// 函数名称 :
//
//
// 函数功能 :
//
//
// 函数参数 :
//
//
//
//
// 函数返回值 :
//
//
// 函数编写修改人 :
// 函数修改日期 :2004-3-22 15:00:50
// ------------------------------------------------
///////////////////////////////////////////////////
1.变量命名:
以匈牙利命名法为基础,如:
int g_iMaxNumber; //全局变量
float fInput; //局部变量
CWnd* m_pOutputWindow; //成员变量前缀如下:
(以下为Charles Petzold 在 programming windows 中使用的标准)
(括号内为该类型的原型)
c char or WCHAR or TCHAR
by BYTE (unsigned char)
n short
i int
x, y int used as x-coordinate or y-coordinate
cx, cy int used as x or y length; c stands for "count"
b BOOL (int);
w WORD (unsigned short)
l LONG (long)
dw DWORD (unsigned long)
fn function
s string
sz string terminated by 0 character
h handle
p pointer补充:
f float
d double(以下为MFC常用的部分标准)
str CString
pt CPoint
t CTime窗口类指针(CWnd)可当作普通指针申明,加前缀p即可,但应在名称中出现
window(或wnd)字样,如下:
CWnd* m_pOutputWindow;
CWnd* m_pFirstInputWnd;命名类的成员变量时加前缀m_
命名全局变量时加g_对一般类的变量进行命名时,若类名称较短,可当作类型处理,小写打头,如下:
CButton buttonHolter
当名称较繁时,可采用如下形式:
MynameClassname
其中,Myname表示当前变量代表的逻辑意义,Classname代表类名(可缩写,简写)
譬如:
CButton HolterButton命名时使用拼音或英语单词(缩写)均可
函数命名使用英语单词组合时一般采用“动词 + 名词”的格式,如:
BOOL OpenWindow(int iIndex); //打开iIndex指定窗口
void ChangeWaveShape(); //改变波形
而不采用如下方法:
BOOL WindowOpen(int iIndex);
void WaveShapeChange();对于获取类的成员变量或设置类的成员变量的函数,一律命名如下:
Get*();
Set*();对于表示信息判断的函数(BOOL型),一律如下命名:
Is*();全局变量命名尽可能使用完整的单词,尽可能长一些。
局部变量应尽可能简短,可多使用常用缩写词。变量一般在使用处声明。
注意不要在switch内声明变量。2.代码格式
尽可能空行,将执行最小功能组或最小意群的代码放在一起,如下:
//……//初始化
Initial();//读取数据
PrepareRead();
Read();
EndRead();//数据处理
CheckData();
DowithData();//数据输出
PrepareWrite();
Write();
EndWrite();//……
括号内的每一项应在逗号后空格,"("后不空格,如:(int iFirstInput, int iSecondInput)
代码缩进应与Visual Studio默认的缩进格式一致(可使用Alt+F8自动校正排版)。每一个if,else,for,while一般应使用大括号
对于if,else有一种情况可除外,即只有一句简单执行语句时,如下:
if(……)
bFlag = TRUE;
else
bFlag = FALSE;一般算术表达式变量之间均应空格,如:
result = a * b / (c + d) + f
仅当两变量之间关系较其它变量在逻辑上明显密切时,可不加空格。
赋值语句格式:int i = 0;
if语句格式: if(bFlag == TRUE);
for语句格式: for(int i = 0; i < MAX; i++)
switch……case语句(若case的内容较复杂,则应加大括号):
switch(iNum)
{
case 1:
FirstFunc();
break; case 2:
SecondFunc();
break; default:
DefaultFunc();
}每行代码不应超过屏幕,即应在不拖动水平滚动条的情况下可浏览整行,
代码太长需分行时,应在本行最后一个逗号后加1空格,再加“\",
分行后,一般应与上一行的括号内的内容左端对齐(可灵活处理),格式如下:
StretchBlt(hdc, xPos + xQiPanLeftTop, yPos + yQiPanLeftTop, Width, Height, hdcMem, 0, 0, Qizi_Width, Qizi_Height,SRCCOPY);3.注释
每个文件最前端应有文件版本号标志及简单说明,如下:
/**************************************************/
/* 文件名:CTree.cpp */
/* */
/* CTree的实现文件,CTree为tree的基类 */
/* 当前版本:1.0.1.9 */
/* */
/* 创建人:XXX */
/* 创建时间: 2001.5.14 */
/* 最后修改者:XXXX */
/* 最后修改时间: 2001.5.20 */
/**************************************************/版本标志说明:1.2.3.4
第一位1.为大版本号 通常软件有重大功能改进时增加此值
第二位2.为小版本号 通常软件发补丁版时增加此值,大版本号更新时,此值归零。
第三位3.功能版本号 软件修补小BUG时的内部调试版本增加此值,小版本号更新时,此值 归零
第四位4.编译版本号 软件每完成一个能成功编译的版本时,此值加1,注:此值不归零。注释多使用//
当要注掉一行以上的连续代码时,一律使用/* */,且退格标在行首,单独成行,格式如下:
/*
if(parentnode->LeftChild == NULL)
{
parentnode->LeftChild = childnode;
childnode->ParentNode = parentnode;
}
*/注释应该尽可能多,尽可能详细、准确。
一般应保证在任意一屏有多于三行的注释。
注释一律采用中文。
连续的注释应尽可能对齐,保持美观,如:
void Initial(HWND hWnd); //程序必要的变量初始化
void DrawQipan(HDC hdc); //画棋盘
void DrawAllQizi(HDC hdc); //显示棋子
void DrawChildQizi(HDC hdc); //显示虚棋子
UINT GetQipanPos(POINT ptMouse); //传入逻辑坐标,得到该坐标在棋盘上的位置函数实现处应至少有函数功能、入参、出参、返回值的注释。除循环计数以外,所有的变量(包括局部变量,临时变量)在声明时均应有注释。
循环计数指定使用:i,j,k,m,n每一个实现算法的代码均应有算法的简短注释,或标明算法说明文档的位置对于起重要作用的变量,在程序中多处说明4.其它
每个函数的内容一般不超过100行,太长时应分拆,集中的算法处理除外。凡可能涉及到优先级时,均应加括号每个头文件均应添加如下类似代码:
#ifndef _INCLUDE_H
#define _INCLUDE_H
……
#endif所有的宏定义放在define_.h头文件中所有非成员变量应在声明时赋初值
指针初值应赋空值,如:int* pCountNum = NULL;
成员变量在构造函数内初始化(包括使用构造初始化列表)仅在代码简短而且逻辑简单清晰的情况下可使用?:操作符
不使用","操作符必要安全性检查:a.所有指针在使用前应进行是否为空的判断b.所有BOOL型的函数应对返回值进行判断c.所有入参和出参应在函数入口对其进行合法性进行验证(空否,范围)d.所有I/O操作,应使用try(),catch()捕捉错误。e.每一次COM(组件对像模型)接口的调用,应检查返回值f.在申请大空间时,譬如new int(1024 * 1024)时,应使用try(),catch()捕捉错误。g.对于DC资源,譬如HDC、HPen、HBrush……等,使用后一定要释放。
现在正在学习vc 能不能问个问题 。net到底是什么呀?我看到一些vc。net vb。net等等不知道到底什么叫。net
http://www.freewebs.com/3jj
1. 函数参数和返回值及其功能的注释
2. 重要变量的注释,特别是全局变量
3. 程序段注释,即某段程序是干什么的
4. 程序流程的简单说明
5. 数据流程的简单说明
6. 特殊的代码处,需以详细注释不过修改别人的程序则不一样,现在修改的,什么都没有,没有缩进,没有注释,没有任何说明,数据库结构也得打开SQL的表去看其结构,表间关系只有靠读程序和数据库里边的内容来判断,所以,算了吧,我也懒得写注释,程序流程了,随之走缩进就严格按照默认的
命名,以匈牙利法为基础,大体上遵循而已变量的声明:
1. 程序全局的,另开一个头文件和实现文件
2. 类全局的,另开一个private或者是public项来声明
3. 函数内的,先一齐声明所有变量,然后再使用注释的上一行如果是代码,则需要加一行空格,如果是第3种注释,则要加至少两个空行.如果是{ 则不空行
函数间必有空行,尽量按照功能连续来放置函数
如果是全局函数,则要另开新的头文件和实现文件,而且一类全局函数是一对头文件(如果函数很少,也可以用同一个头文件)
如果有define的,则要另开一个新的头文件
谢谢happyparrot提出了这个问题,
谢谢“天外流星”给出了如此详细的规范,:)
一直以来都在想着如何使自己的代码写得规范,
却又苦于无人指导,我想我在这可以有进展了,:)
这是我们公司的:
一、设计
1、设计应该考虑到可移植性、可扩展性。
2、注意界面和实现的分离。
二、编码
1、C++语言优先权。除接口、界面等与Windows相关的程序外,能用标准C++解决的问题尽量用标准C++解决,而不要使用Windows库及第三方库。
2、代码力求清晰、简明,风格大体一致。
3、不要使用无意义的名字做变量名、函数名、类名等。
4、为了便于交流和维护,函数声明前应该有函数功能、参数和返回值注释说明,类、结构体和枚举及成员应该有必要的说明。在程序中加入必要的注释。
三、编码风格参考:
.h文件
/*
(版权说明、文件说明、作者、修订说明)
*/#include <iostream>
#include <string> // 我的工作
enum ZMyWork
{
ZMY_WORK_TEACHER = 1, // 教师
ZMY_WORK_WORKER = 2 // 工人
};// 我的信息
struct ZMyInfo
{
std::string Name; // 名字
int Age; // 年龄
};// 我自己类
// 描述〈可选〉
class ZMySelf
{
public:
// 构造函数
ZMySelf(void); // 获取我的名字
// 返回我的名字
std::string GetName(void) // 重新设置我的信息
// Name ---- 新的名字
// Age ---- 新的年龄
// 成功返回true,失败返回false
bool Reset(const std::string& Name, int Age);
private:
std::string m_Name; // 我的名字
int m_Age; // 我的年龄
};
...
//------------------------some func end-------------------------------
我一般是这样的,多了就不写了
我刚刚开始用VC编程!有许多问题不清楚!
但看了看林锐的《C/C++高质量编程》,觉得里面的规范确实值得学习!
但如果具体每个人都那样操作,可能会很难,所以觉得也只有大家慢慢提高自己的编程素质,才能有更好的团队开发,有更优秀的作品!努力 + ing !!!
设计阶段:
1 先弄清楚软件所实现得流程;
2 找出核心模块;
编码阶段:
1 编码时,变量,函数名用统一得规则命名,用英文命名,不用拼音;
2 编码时,采用缩进规则;
3 如果有相似得功能,尽量做成公共函数;
4 公共变量尽量放在文件得开头,局部变量尽量放在函数得开头,便于查找;
5 如果有拿不准得情况,在代码中一定要注释,否则,时间一长,连自己也弄不清了。而且,要尽快弄清楚。
6 一个函数得功能,局部变量,参数,一定要标注清楚;
7 每个模块,C文件,CPP文件,H文件的开头,一定要注释清这个文件实现的主要功能,或者功能库,尽量用E文
8 C和CPP文件也按功能划分,然后,公用的部分,放在一个或几个文件里;
9 实现功能时候,尽量使用标准的C库和C++库。
我现在只想到了以上的少量经验。如有遗漏,后面再补充。
2. 函数的返回值必须要有意义,并且注意可扩充性
3. 头文件中 变量/函数的定义与编译器自己产生的区分开来
4. 尽量多一些注释,包括本模块的功能,函数的功能,变量的要求,返回值的意义等.
5. 尽力多采用C++的风格 比如少用宏定义之类的.
6. 多注意函数/代码的安全性,比如指针是否为空,下标是否越界等,在开发调试的时候可以用ASSERT进行提示
7. 分析问题的过程
7.1 功能目标是什么 大致的目标确定 然后对这些目标细化
7.2 关键的功能是什么
7.3 有何具体要求,难度,难点何在
7.4 需要注意的问题
7.5 进行按功能模块分类..暂时想到这么多...感谢楼主呀...
WinMain(int,还是WinMain (int,?
我的写程序方法就是<<我是一只鱼>>自由的游来游去.没有规则就是我的规则.
这样做的确可以把信誉分成功减到75分:)
呵呵!
类型函数名各占取一行,类似:
VOID MyFunction(int iCount)
定义时使用:
VOID
MyFunction(
int iCount)
{
......
}
这样写的好处是什么?谢谢!
if ( var1 == XXX )
{
...
}
比如: gsc_xxx 表示是一个全局静态常量;编码采用成对原则:
比如 有new 就写 delete
一写for,就输入 for (; ; )
{
}
一打{就补换行和}设计采用极限编程思想,先实现核心框架再扩展!格式基本上采用公司规范!和华为公司的要求差不多!大家可以更深入的探讨各种设计思路,比如一般错误处理采用什么机制,如何安排调试时间等等!
MFC 用匈牙利
其他用 .NET 风格
CString m_strConnect;
m_strConnect.Format("Provider=OraOLEDB.Oracle; Data Source=%s; User ID=%s; PassWord=%s",strDataSource, strUserID,strPassWord);
我的方法:
1:
CString m_strConnect;
m_strConnect.Format(
"Provider=OraOLEDB.Oracle; Data Source=%s; User ID=%s; PassWord=%s",
strDataSource,
strUserID,
strPassWord);
2:
m_strConnect.Format("Provider=OraOLEDB.Oracle; Data Source=%s; User ID=%s; PassWord=%s",
strDataSource,
strUserID,
strPassWord);
3:
m_strConnect.Format("Provider=OraOLEDB.Oracle; Data Source=%s; User ID=%s; PassWord=%s",
strDataSource, strUserID, strPassWord);
4:
m_strConnect.Format(
"Provider=OraOLEDB.Oracle; Data Source=%s; User ID=%s; PassWord=%s",
strDataSource, strUserID, strPassWord);
在一个project中,坚持一种统一的注释方式,函数调用习惯,
(比如,在一个函数中,是用
bool someFunction(Type& result); // return是否成功,result为结果。
还是
Type someFunction(void); // 直接返回结果,如果为某个确定特殊值则失败。
)
还有资源的管理方式,异常的使用,先把这些基础结构定义好,
在编程的过程中,最重要的是保持程序逻辑结构的清晰简单。但要在一个project自始至终的坚持一种统一的风格比较困难,会有各种客观的原因
促使你放弃它,并为自己找到很好的借口--工期太紧,特殊的客户需求等等。
总之,实际的开发实际上太可能做到理想状态,比较理想都不能。就算是---你也一直
认为自己是---一个优秀的程序员。
长的可以这样排版Status = lpAcceptEx(
g_sListen[nIndex],
lpAcceptIoContext->sClient,
lpAcceptIoContext->wsaBuffer.buf,
0,
sizeof(SOCKADDR_IN) + 16,
sizeof(SOCKADDR_IN) + 16,
&dwBytes,
&lpAcceptIoContext->ol
);
http://www.xxxx.comModule name VNetSvr.h
Abstract:
Author:
PPP [email protected]
Environment: Windows2003 Server
Notes:
Revision History: created: 26:06:2004 11:05
--*/函数:
DWORD IOCOMP_Connect(char *pszRemoteIPAddr, unsigned short uRemotePort)
/*++Function Description: 创建一个套接字,设置相应的属性,连接到在参数里指定的远程地址,
并与完成端口相关联,然后返回此连接的IDArguments: pszRemoteIPAddr - 要连接的远程IP地址
uRemotePort - 要连接的远程端口Return Value: 连接成功返回连接的ID;失败返回0。--*/
{
struct sockaddr_in InterNetAddr;
SOCKET s;
int nResult = 0;
LPCOMMON_OBJECT lpCommonObject = NULL;
HANDLE hrc = NULL;
ZeroMemory(&InterNetAddr, sizeof(InterNetAddr));
InterNetAddr.sin_family = AF_INET;
InterNetAddr.sin_port = htons(uRemotePort);
InterNetAddr.sin_addr.s_addr = inet_addr(pszRemoteIPAddr);
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
return 0;
}
//
// 设置套接字属性
// if (!IOCOMP_SetSocketOpt(s))
{
closesocket(s);
return 0;
}
nResult = connect(s, (PSOCKADDR)&InterNetAddr, sizeof(InterNetAddr));
if (nResult != 0)
{
closesocket(s);
return 0;
}
//
//将新建立的套接字与完成端口相关联
//
if (CreateIoCompletionPort((HANDLE)s, g_hIOCP, (ULONG_PTR)0, 0) == NULL)
{
closesocket(s);
return 0;
} lpCommonObject = IOCOMP_GetCommonObjectNode();
if (lpCommonObject == NULL)
{
closesocket(s);
return 0;
} lpCommonObject->sClient = s; strcpy(lpCommonObject->chClientAddr, pszRemoteIPAddr);
lpCommonObject->nClientPort = uRemotePort;
IOCOMP_CreateSocketID(lpCommonObject);
InterlockedExchangeAdd(&g_lConnectedNum, 1); return lpCommonObject->dwSocketID;
}// end of IOCOMP_Connect
===================================传说中的无招胜有招?
===============================================
我把所有必须有所呼应的都一起写,包括与具体函数有关的。比如
_pRs->Open();
_pRs->Close();
中间再加代码,当然,类似的还有许多。