0. 序言
工作的需要,最近在接手一个C++项目。自己在校学习期间,因为懒惰,对于C++这样的巨型语言,是能躲就躲的,因此学的一知半解,导致现在工作时的无能为力。但是,指责所在,躲无可躲,只能做一些亡羊补牢之事。下面的一系列文章,就是自己边工作边学习的记录,算是学步时的点滴。内容会持续更新,有错误之处,敬请指教。
1. class编写过程中的注意事项
-
在编写类的时候,一般将类的申明和实现分开,这样便于类的实现和调用。比如定义一个名为:
-
头文件中最好用防卫式申明,目的是防止文件的内容被多次包含(多次包含之后会出现重复定义或者多次申明的错误。)如:
laptop.h
#ifndef _PROJECT_SUBFOLDER_LAPTOP_H_ // 此处推荐使用Google编程规范:项目名_子文件路径_文件名
#define _PROJECT_SUBFOLDER_LAPTOP_H_
// define a laptop class
calss Laptop // 类名首字母大写
{
public:
// member functions; // 成员函数一般为public属性;
double getVolt() const { return volt_;} //不会改变成员变量的函数申明为常函数const;
private:
// member attributes;// 成员变量一般设为private;
};
#endif // _PROJECT_SUBFOLDER_LAPTOP_H_
-
类的构造函数
为了通用性,一般为一个类设至少两个构造函数,0参数构造函数,多参数构造函数;当使用多参数构造函数的时候,推荐使用**初始化列表**来初始化成员变量。(在函数内的叫赋值,不是初始化。赋值和初始化列表的区别是内存开销上不一样。)
class Laptop
{
public:
Laptop(){}//默认构造函数
Laptop(double value = 0, double volt)// 多参数构造函数,注意不能将所有的值设为默认值。请思考为什么
:value_(value), volt_(volt){} // 初始化列表
private:
// ...
}
-
尽可能使用引用传参
引用传参比值传递的优点是效率高,开销低。另外,传引用可以数据双向传递(这在很多情况下是不希望发生的,这时可以传递**常引用**)。另外,对于内置类型,传值和传引用的效率相差不多,一般可以传值,对于构造类型,请传引用。关于**传值**,**传引用**,**传指针**之间的区别和联系,将在专门的文章里讨论。
在可能的情况下,函数返回值也请尽量使用引用。这里需要注意的是,将引用作为函数返回值的条件是引用的宿主对象至少要在函数调用现场有生命并可见!!,否在,不能将应用返回,因为局部变量在函数调用结束的时候就已经被回收,它的生命周期已经到了尽头,再去返回它的引用,明显是会出错的。将应用作为函数返回值的一个很典型的应用是对一些二元操作符的重构。这里给出几个例子:
例1:+=
重构
class Point
{
public:
Point(){}
Point(double x, double y)
:x_(x), y_(y){}
void setx(double x){x_ = x;}
void sety(double y){y_ = y;}
Point & operator += (Point & b)
{
this -> x_ += b.x_;
this -> y_ += b.y_;
return this;
}
private:
double x_;
double y_;
};
例2:<<
重构
class Point
{
public:
//....
// 显示点p(x,y)
}
-
重构/重载要全面
在类中重构或者重载函数的时候,为了使用的方便,请尽可能全面的重构/重载。比如,有一个复数类,里面重载加法运算符,这时候要考虑到用户可能会将复数与实数相见,复数与复数相加,实数与复数相加,这些都要进行重载。重构函数的时候也同样。
-
外部接口放在类的最前面,写好使用说明,包括:接口功能的描述,输入参数的描述,输出参数的描述。