4. 成员设计规范
4.1. 一般规范
√ 要求重载成员之间的相同参数的顺序和名称要一致。
例如,
class EventLog
{
public:
EventLog();
EventLog(const string& logName);
EventLog(const string& logName, const string& machineName);
}
×
不要在重载中随意地给参数命名。
√ 要求在成员方法的签名添加”const”,如果成员方法不需要改变对象的状态。
例如,
class DocumentEnvironment
{
public:
const std::string& GetAuthor(){…}//不好
const std::string& GetAuthor() const{…}//好
}
×
不要对参数为指针和数字类型的函数进行重载。
例如,
class StockHolder
{
public:
void SearchStock(int stockCode);
void SearchStock(const wchar_t* stockName);
}
//如果按照下面的方式调用
StockHolder stockholder;
Stockholder. SearchStock(0);//调用存在二义性
√ 要求优先使用重载,而不是定义具有默认参数的成员。
例如,
class Point
{
public:
void Move(int x,int y=0){…}//不好
//好
void Move(int x){…}
void Move(int x,int y){…}
}
√ 要求优先使用重载,而不是定义具有默认参数的成员。
√ 要求对短小的函数合理使用inline。
×
不要定义inline virtual的成员函数。
例如,
class Point
{
public:
inline virtual void Move(int x,int y=0){…}//不好
void Move(int x,int y=0){…}//好
virtual void Move(int x,int y=0){…}//好
}
4.2. 构造/析构函数的设计
√ 要求在构造函数中作最少的事情且不要在构造函数中抛出异常。
l
推荐避免在构造函数中出现隐式赋值。
例如,
class A
{
public:
A(int a){..} //不好
explicit A(int a){..} //好
}
√ 要求重新编写/禁用拷贝构造函数和operator=重载
如果编译器生成的拷贝构造函数和operator=重载不是所期望的:如果需要这两个操作,重新编写这两个函数;否则,显示地禁用它们。
例如,
//显示地禁用拷贝构造函数和operator=重载
class Envidence
{
private:
Envidence(const Envidence& other){…}
Envidence& operator=(const Envidence& other){…}
}
√ 要求使
将基类析构函数设为
public
且virtual,或设为protect而非virtual。
如果允许通过指向基类Base的指针执行删除操作,那么将基类析构函数设为public且virtual,或设为protect而非virtual。
例如,
class AuthrizationStrategy
{
public:
AuthrizationStrategy();
virtual AuthrizationStrategy();
};
class LogonSession
{
public:
LogonSession ();
protected:
LogonSession ();
};
4.3. 操作符重载
√ 要求以对称的方式重载操作符
例如,如果重载了operator==,那么应该同时重载operator!=。同样,如果重载了operator<,那么应该同时重载operator>。
×
不要提供类型转换操作符,如果没有明确的需求。
×
不要提供隐式类型转换操作符,如果该类型转换可能会丢失精度。
例如,由于double的覆盖范围比int要广,因此不应该存在把double隐式地转换为int的操作符。即使类型转换可能会丢失精度,也可以提供显式的类型转换操作符。
4.4. 字段的设计
l
推荐在结构中提供public字段(默认)
例如,
struct PageSetting
{
int PageCount;
int LeftMargin;
…
}
×
不要在类中不要提供public/protected字段
例如,
class ChangeManager
{
public:
ChangeManager(int changeType, int changeEvent)
: m_changeType(changeType),
m_changeEvent (changeEvent),
{…}
int GetChangeType() const{return m_changeType ;}
int GetChangeEvent () const{return m_changeEvent;}
private:
int m_changeType;
int m_changeEvent;
}
4.5. 参数的设计
×
不要使用保留参数。
例如,
//不好
void Method(SomeOption option,object reserved)
//不好
void Method(SomeOption option)
l
推荐将所有的引用/返回参数放到函数签名的后面,这样可以使函数签
名更易于理解。
例如,
bool GetObjectFromID(VOBJID32 oidObject,vtl::Cv_PTR& objReturned);
void CreateNullSpreadItem(VCLSID clsidProxy,VOBJID32& oidNewSpreadItem);
√ 要求在重载函数或实现接口函数时保持参数命名的一致性。
例如,
//重载时
bool Equals(const string& value);
bool Equals(const string& value,bool ignoreCase); //好
bool Equals(const string& other,bool ignoreCase); //不好
//实现接口时
public ISpreadItem
{
virtual bool Transform(const Matrix& matrix) = 0;
}
classs SpreadItem : public ISpreadItem
{
public :
bool Transform(const Matrix& matrix); //好
bool Transform(const Matrix& trasformMatrix); //不好
}
l
推荐不要使用不定长的参数。
例如,
class StringUtil
{
string Format(const wchar_t* format,…);//不推荐
}
×
不要使参数长度超过一定的数量(7个以内)。
√ 要求对于不会被改变的简单类型的参数使用值传递,而不是使用引用传递。
例如,
void ShowMessage(const std::string& message,int option);//好
void ShowMessage(const std::string& message,const int& option);//不好
void ShowMessage(const std::string& message,const int option);//不好
√ 要求对于不会被改变的复合类型的参数使用引用传递,而不是使用值传递。
例如,
void Log(const std::string& message,const Color& backgroundColor);//好
void Log(std::string message, Color backgroundColor);//不好
4.6. 返回值的设计
×
不要返回字段的非const引用,除非完全必要。
例如,
class PhoneBook
{
public:
Address& GetAddress() const{return m_address ;}//不好
const Address& GetAddress() const{return m_address ;}//好
private:
Address m_address;
}
√ 要求返回字段的const引用。
Class Document
{
public:
const DocumentInfo& GetAddress() const{return m_documentInfo;} //好
const string& GetAddress() const{return m_fileName;}//好
//或
const wchar_t* GetAddress() const{return m_fileName;}//好
private:
DocumentInfo m_documentInfo;
string m_fileName;
}
4.7. 全局变量/函数/常量/宏的设计
×
不要使用全局变量和函数,将全局变量和函数作为某个类的静态成员函数。
例如,
//不好
extern void ToCMYKColor (Color& color);
extern void ToRGBColor(Color& color);
//好
class ColorConverter
{
public:
static void ToCMYKColor (Color& color);
static void ToRGBColor(Color& color);
}
×
不要使用”Magic Number”,使用const修饰符来进行定义。
×
不要使用#define来定义常量,应该使用const修饰符或采用enum来定义常量。
例如,
//不好
#define FITUNKNOWNBLOCK 0
#define FITPICTUREBLOCK 1
#define FITTEXTBLOCK 2
//好
enum kFitBlockType
{
kFitBlockType_Unknown,
kFitBlockType_Picture,
kFitBlockType_Text
}