(1)函数的所有参数必须命名,并且必须在函数声明中说明各个参数的类型。
(2)禁止函数的参数为空。
例子:
|
正确写法 |
错误写法 |
|
F(int a, char *b); |
f(int, char*); |
|
F(int a, char *b) { ...} |
f(a, b) int a; char *b { ...} |
|
F(void); |
f(); |
对于自动产生的代码可能违反该规则的例子:
void CTest2View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
你可采用两种方法:一是修改成符合格式的代码形式;
二是无法修改,则在函数前面添加注释:“此处为自动产生的代码,不方便修改。”。
不允许在函数调用中使用赋值运算符(=, +=, -=, *=, /=, %=, >>=, <<=, &=, |=, ^=,++,--)。目的是去除有关赋值顺序的不明确性。
例子:
|
正确写法 |
错误写法 |
|
n=f(b); b++; |
n=f(b++); |
不允许在if , while , for , switch控制指令中的条件表达式中使用赋值运算符(=, +=, -=, *=, /=, %=, >>=, <<=, &=, |=, ^=,++,--)。
例子:
|
正确写法 |
错误写法 |
|
X -= dx; if (x) { ... for (i=j=n; i > 0; i--, j--){ ... |
if (x -= dx) { ... for (i=j=n; i-- > 0; j--) {.. |
在表达式内部,为了规避赋值顺序的不明确性,做如下规定:
(1)一个运算项只能被赋值一次。
(2)如果有多个赋值运算符,一个被赋值的运算项能且只能出现在它被赋值的位置。
例子:
|
正确写法 |
错误写法 |
|
|
i = t[i++]; a=b=c+a; i=t[i]=15; |
在语句体内,任何声明必须放在语句体的开始处。即:必须先声明后使用,而且必须集中在语句体的开始处声明。
例子:
|
正确写法 |
错误写法 |
|
{ int n; CAboutDlg aboutDlg; aboutDlg.DoModal(); n=3; } |
{ CAboutDlg aboutDlg; aboutDlg.DoModal(); int n; n=3; } |
不允许使用缩写的布尔表达式。
例子:
|
正确写法 |
错误写法 |
|
AlwaysTrue = true; while (AlwaysTrue == true) { if (test == true) { if (ar.IsStoring()==true) { |
while (1) { if (test) { if (ar.IsStoring()){ |
break 和 continue指令禁止使用在控制语句(for, do ,while)中。然而,break指令被允许使用在switch语句体中。
像goto一样,这些指令会改变代码的结构。在循环中禁止使用它们将使代码比较容易理解。
例子:
|
正确写法 |
错误写法 |
|
int i,n; for (i=0;i<10;i++) { if (………) i=10; } while (b==false) { if (n==10) { b=true; } } |
int i,n; for (i=0;i<10;i++) { if (………) break; } while (b==false) { if (n==10) { break; } } |
禁止通过串联(连续的)的调用方法,调用一个在用户类中不知道的类方法(隐式使用)。
下列表达式都是不允许的:u.v.a, u.v.f(),u.g().a, u.g().f(),(表达式中使用->操作符也是一样)。
例子:
|
正确写法 |
错误写法 |
|
|
myWindow.itsButton.push(); Error->pos.line; |
一个代码文件中,每个函数都必须属于一个相同的类。
C函数被认为属于main类。
默认情况下,一个代码文件有一个如下的后缀:*.cc, *.cxx, *.cpp,*.C or *.c。
例子:
|
正确写法(解释) |
错误写法(解释) |
|
在一个.cpp文件中,只包含一个类的实现。 在一个.cpp文件中,只包含c函数的实现 |
在一个.cpp文件中,包含两个类的实现。 在一个.cpp文件中,既包含一个类的实现又包含c函数的实现。 |
代码文件不能包含任何类的声明。
C函数被认为属于main类。
默认情况下,一个代码文件有一个如下的后缀:*.cc, *.cxx, *.cpp,*.C or *.c。
例子:
|
正确写法(解释) |
错误写法(解释) |
|
在一个.cpp文件中,只包含一个类的实现。 |
在一个.cpp文件中,同时包含一个类的声明和实现。 |
三重条件操作符? ... : ...禁止使用。
在控制语句段(if , for , while , do)中必须使用{}。消除结构范围的不清楚性以及使代码易读易改。
例子:
|
正确写法 |
错误写法 |
|
if (x == 0) { return; } else { while (x > min) { x--; } } |
if (x == 0) return; else while (x > min) x--; |
当删除数组时必须使用[]。确保恰当的内存被释放。
例子:
|
正确写法 |
错误写法 |
|
int *table = new int[7]; delete [] table; |
int *table = new int[7]; delete table; delete [10] table; |
每个类都必须明确包含它的默认构造函数。确保作者已经考虑到初始化该类的方法。
例子:
|
正确写法 |
错误写法 |
|
class aClass { ... aClass(); ... }; |
|
每个类都必须明确包含它的析构函数。确保作者已经考虑到销毁该类的实例的方法。
例子:
|
正确写法 |
错误写法 |
|
class aClass { ... ~aClass(aClass &object); ... }; |
|
类的接口必须是纯粹的函数:数据成员的定义被限制。
访问一个对象状态的好的方法是通过它的方法,而不是对象的数据成员。类的数据成员应当是private或者至少是protected。
例子:
|
正确写法 |
错误写法 |
|
class CTest2App : public CWinApp { public: int getactstate(); private: int m_act; |
class CTest2App : public CWinApp { public: int m_actstate; |
表达式的复杂度必须小于一个给定的值。复杂度的计算与语法树以及它的节点个数有关。审核值复杂级为24。
例子:
(b+c*d) + (b*f(c)*d)
有 8个操作符和7个操作数.,语法树有16个节点,复杂度为16。
在表达式中,每个二元的和三元的操作符必须放在()中。
当右边的操作符与当前操作符同是+或者*则,禁止为右边的操作数使用();
同上,赋值操作符右边的操作数禁止使用();
禁止在表达式的第一级使用();
例子:
|
正确写法 |
错误写法 |
|
result = (fact / 100) + rem; result = (fact * |
result = fact / 100 + rem; result = ((fact / 100) + rem); result = ((fact * ( |
每个函数必须声明它的类型。如果不返回任何值,它必须被声明为void类型。
循环的计数器(在for循环中)必须在循环的初始化语句段中初始化。由循环头中的第三个元素来判断哪个是循环计数器。
例子:
|
正确写法 |
错误写法 |
|
for (i = 0; i < 10; i++) ... |
for (i; i < 10; i++) ... for (j = 0; j < 10; i++) ... for (j = 10; i < j; i++) ... for (j = 1; i < funct(j); i+=j) ... |
如果使用友员类,则友员类必须在类的开始处被声明(在类的成员被声明之前)。
不使用函数指针。
|
正确写法 |
错误写法 |
|
|
void (*func_1)(int); typedef void (*PFUNC)(int); PFUNC pfunc; |
特定的名字不能用来声明或者定义函数,也不能调用。默认情况下,不禁止任何函数名。主要用于禁止使用一些比较危险的系统函数。
目前我们不做任何限制。
全局变量必须在定义的时候初始化。不是所有的编译器都给予相同的默认值。可以通过控制变量的值来避免一些不期望的动作。当声明全局变量的时候就赋初值可以确保在使用它们之前初始化。
文件必须有一个头注释。头注释的格式如下:
///////////////////////////////////////////
// Name: program
// Author: Andrieu
// Date:
// Remarks: example of comments
///////////////////////////////////////////
函数和类必须有注释。只要有一个/*,或者//开始的注释就可以了。
一个头文件一定不能包含多于一个类的定义。嵌套类可以接受。
头文件不能包含代码段(例如:数据和函数定义)
头文件的主结构应当是这样的:
#ifndef <IDENT>
#define <IDENT>
...
#endif
或者
#if !defined (<IDENT>)
#define <IDENT>
...
#endif
这里,<IDENT>与头文件的名字保持一致。
函数、参数、属性或者变量类型必须被明确定义。
|
正确写法 |
错误写法 |
|
void aFunction(int value); |
aFunction(value); |
只有一些类型的模块被允许包含在其他的模块中。默认情况下,头文件模块可以被包含在头文件模块和代码模块。
内联函数必须在类声明文件中(.h文件)中定义。
在宏的定义中,每个宏参数都应当包含在()中。
|
正确写法 |
错误写法 |
|
#define GET_NAME(obj, |
#define GET_NAME(obj, |
对于字符串常量使用全局或者静态变量,其余的常量可以使用宏定义
|
正确写法 |
错误写法 |
|
const char *string = "Hello world!\n"; #define value 3 |
#define string "Hello world!\n" |
使用内联函数替代宏函数。相对于宏函数,内联函数可以检查它的参数类型。
|
正确写法 |
错误写法 |
|
inline char *GetName(aClass &object) { return(object.name); } inline min (int i, int j) { return (i<j)?i:j; } |
#define GetName(s) ((s)->name) #define MIN(i,j) ((i)<(j)) ? (i) : (j) |
文件名必须来自于在文件中声明或者定义的类的名字。
每个语句中,赋值操作符(=, +=, -=, *=, /=, %=, >>=, <<=, &=, |=,^=, ++, --)不能使用多于一次。消除运算顺序的不清楚。
|
正确写法 |
错误写法 |
|
c = 5; b = c; b++; a = (b * c) + 5; |
b = c = 5; a = (b++ * c) + 5; |
除了在参数列表中配置的那些指令,其它未指明的指令不允许使用。
只有 #line 和 # alone不可以使用。
“define”: #define may be used
“include”: #include may be used
“if”: #if, #ifdef and #ifndef may be used
“pragma”: #pragma may be used
“undef”: #undef may be used
“line”: #line may be used
“error”: #error may be used
“none”: # none may be used
定义哪些代码可以被分析,哪些代码拒绝c++RuleChecker的分析。
成员函数一定不能返回成员数据的指针或者成员数据的非常量形式的引用。帮助确保遵守数据封装。
使用ptr->field格式的语法,不能使用(*ptr).field格式的语法。
每一个被明确声明为指针(使用”*”)的自变量,必须在声明的时候初始化。确保指针变量在使用之前就被恰当的初始化。
|
正确写法 |
错误写法 |
|
int* y=&x; ... |
int *y ; *y=&x ; |
函数一定不能返回一个非静态的本地变量的指针。避免使用一个不在生命周期内的变量的指针。
变量的声明必须是如下的格式:
type variable_name;。
禁止在一个声明中同时声明多个变量。
每一行不能多于一个语句。一个语句跟随一个{,或者一个{跟随一个语句在一行之内都是允许的,但是如果一行之内语句跟随{再跟随语句就是不允许的。
|
正确写法 |
错误写法 |
|
x = x0; y = y0; while (IsOk(x)) { x++; } |
x = x0; y = y0; while (IsOk(x)) {x++;} while (IsOk(x)) {x++; } |
在switch语句体中,为了覆盖没有case的其它情况强制使用default
例子:(正确)
class inherclass : public Base1, private Base2
{...
禁止函数使用可变量参数,例如:va_list类型和… 。
变量不能使用struct或者union直接声明,必须定义一个中间类型。
|
正确写法 |
错误写法 |
|
typedef struct { ... } typeName; typeName varName; struct structName; typedef struct structName { ... struct structName *ptr; } typeName; typeName varName; |
struct { ... } varName; struct structName { ... }; struct structName varName; |
在赋值操作符的定义中,必须检查参数与this(或者与*this)是否相等,如果相等,必须返回*this。
例子:
try {
someFunction();
}
catch (exception& ex) { // 这里,我们通过引用捕获异常
cerr << ex.what();
}
new必须遵守:
返回值必须是void *
第一个参数类型必须是site_t
delete必须遵守:
返回值必须是void
第一个参数必须是void *
第二个参数类型必须是site_t
new的一般模式:
第一个参数的类型必须是size_t。
如果还有其他参数,每个参数都必须有一个默认值。
++和--操作符必须按照如下方式声明:
class Example {
public:
Example& operator++(); // 前缀++
const Example operator++(int); // 后缀++
Example& operator--(); // 前缀 --
const Example operator--(int); // 后缀 --
}
默认情况下,不禁止任何字符。
默认情况下,不禁止任何字符。
默认情况下,不禁止任何类型。
发表于 @ 2006年11月28日 15:50:00 | 评论( loading... ) | 举报| 收藏