1. 将构造函数声明为__explicit__,以阻止它们被用来执行隐式类型转换;
class Rational{
public:
explicit Rational(int numerator = 0, int denominator = 1);
const Rational operator+(const Rational& rhs) const;
...
};
Rational oneHalf(1, 2);
// 下式非法:2被禁止隐式转换为Rational类型
Rational result = oneHalf + 2;
2. 按值传递内置类型,按址传递(pass by reference to const)用户自定义类型;
3. 尽量以const、enum、inline替换#define;
// 对于单纯常量,以const或enum替换#define
const int Size = 5;
enum {Size = 5};
4. 尽可能使用const;
ClassA operator*(ClassA lhs, ClassA rhs); // 不要采用这种方式!
// 令函数返回常量
const ClassA operator*(const ClassA& lhs, const ClassA& rhs);
5. 确定对象被使用前已先被初始化;
- 类构造函数使用成员列表初始化;
- 为内置对象手动初始化;
- 以local static对象替换non-local static对象(使用返回指向该对象的引用的函数,该non-local static对象在该函数内即为local static);
6. 若不想使用编译器自动生成的函数,可将相应的成员函数声明为private并且不予实现;
// 不使用copy构造函数和copy赋值操作符
class Home{
// ...
private:
Home(const Home&);
Home& operator=(const Home&);
};
7. 为多态基类声明virtual析构函数。
- 多态基类应该声明一个virtual析构函数。如果class带有任何virtual函数,就应该有一个virtual析构函数。
- 若类的设计目的不是作为基类使用,或不是为了具备多态性,就不该声明virtual析构函数。
8. 在__operator=__中处理“自我赋值”。
Home operator=(const Home& rhs){
// 证同测试
if (this == &rhs) return *this;
...
return *this;
}
9. 为防止资源泄漏,使用RAII对象。
// 调用工厂函数返回对象指针
Investment* pInv = createInvestment();
...
delete pInv;
// 改用RAII class,如auto_ptr、tr1::shared_ptr
// RAII对象在构造函数中获得资源并在析构函数中释放资源
std::auto_ptr<Investment> pInv(createInvestment());
std::tr1::shared_ptr<Investment>pInv(createInvestment());
10. 使用non-member non-friend函数替换member函数
// 使用non-member函数并和class放于同一namespace中
namespace WebBrowserStuff{
class WebBrowser {...};
void clearBrowser(WebBrowser& wb);
}
// 若所有参数都需类型转换,应采用non-member函数
const Rational operator*(const Rational& lhs, const Rational& rhs);
10. 区分接口继承和实现继承
- 纯虚函数只指定接口继承;
- 虚函数指定接口及缺省实现的继承;
- non-virtual函数指定接口及强制实现的继承(严禁在派生类中重定义);
11. 考虑virtual函数外的选择
/* virtual函数是动态绑定的,但缺省参数是静态绑定的。
可以使用“非虚函数接口”替代virtual函数:
令基类的一个public非虚函数调用private虚函数,后者可被派生类重新定义;非虚函数指定缺省参数和接口,private虚函数负责实现。 */
class Shape{
public:
// public non-virtual interface
void draw(int num = 1) const {
doDraw(num);
}
...
private:
// private virtual implementation
virtual void doDraw(int num) const = 0;
};
class Rectangle: public Shape{
public:
...
private:
// 不须指定缺省参数
virtual void doDraw(int num) const;
};
12. 复合(composition)塑模has-a
/*
复合指一种类型的对象内含其他种类型的对象。常见的形式有“has a”和“is-implemented-in-terms-of”。
*/
// has-a
class Address {...};
class PhoneNumber {...};
class Person {
public:
...
private:
string name;
Address address;
PhoneNumber phonenumber;
};
// is-implemented-in-terms-of
// 根据std::list对象实现一个Set对象
template<class T>
class Set {
public:
void insert (const T &item);
std::size_t size() const;
private:
std::list<T> rep; // 用来表述Set的数据
};