7、如果函数的参数或者返回值是对象,则尽量使用引用,而不是值传递。
比如,使用myMethod(const SomeClass & object),而不是myMethod(SomeClass object)
原因:1)性能。值传递总是使用拷贝构造函数创建临时变量并在函数退出时销毁该对象。
2)以基类类型的对象传递继承类对象时,会导致内容截断。
8、应该避免使用可变参数列表
可变参数列表禁用了C++强大的类型检查机制;会带来类型匹配方面的问题。
很多时候,可变参数列表可以使用“函数重载”或者“默认参数”来代替
9、使用new和delete,而不是malloc,realloc,free。
一方面是保持代码风格的一致性,另一方面new和delete才可以安全的分配内存
10、如果类有动态分配的内存,那么应该为类定义拷贝构造函数和赋值运算符函数。
因为类的这俩默认函数不会动态分配内存,而只是拷贝指针神马的。
11、赋值运算符应该返回一个 *this 的引用。
12、赋值运算符应该检查到自身的赋值
13、重载的派生类的赋值运算符必须显式的执行基类的赋值运算符的操作
Derived & Derived::operator=(const Derived &rhs){
if(this != rhs){
Base::operator=(rhs);
//then do assignment for own studff
}
return *this;
}
如果基类的赋值运算符是自动生成的,则使用 static_cast(*this)=rhs;
15、当且仅当类中存在虚函数时,其析构函数才被声明为虚函数。
若某派生类的基类析构函数不是虚函数,当该派生类对象通过基类指针被delete时,仅有基类的析构函数被调用,派生类析构函数不会被调用。
16、运算符== 和 != 任意一个被重载时,另外一个也应该被重载。
大多数情况下,运算符!=都可以使用==表示:
bool C::opeator!=(const C &lhs){
return !(this == lhs)
}
17、运算符|| 和 && 都不应该被重载。
使用|| 和 && 时,如果最终结果已经被确定了,那么求值就不会进行下去,这叫做“短路求值”
如果该运算符被重载了,那么该“短路求值”就不存在了。
18、
is-a表示继承,has-a表示容纳
class B:public A{//B is-a A
private:
A a_;//B has-a A
};
19、非虚函数不可以由子类重定义
原因1:如果该函数需要被定义,那么子类不应该从父类继承,子类父类不构成is-a关系
原因2:非虚函数使用静态链接,使用基类引用总是调用基类的函数,即使这个基类引用实际上引用的是派生类的对象
20、从父类继承的带有默认参数的函数,不可在子类中重定义其参数
21、避免使用私有继承。可以使用聚合关系代替私有继承
class C{ ... private: B b_; } rather than: class C:private B
22、避免使用向下继承(将基类指针用static_cast转换为派生类指针)
Derived = static_cast<DerivedClass *>base;//不好!
23、捕获异常对象时,应使用异常对象的引用作为catch的参数
try{ } catch(Exception &exception){ }
24、正确区分并使用成员函数、非成员函数和友元函数
a)虚函数必须是类的成员函数
b)>>和<<运算符不可重载为成员函数。如果他们要访问类中的非公有成员,就将他们声明为友元函数。
25、隐式生成的函数如果不被使用,应该显示的禁用。
例如:将以下函数声明为私有,并且不定义,在系统无意中调用时,编译器会报错
class C{ private: C &operator=(const C &rhs);//Do not define }
26、单例对象优于全局变量
27、如果一个函数,能够仅仅使用类的其他公用函数即可实现,那么它不应该作为当前类的成员函数
28、公有成员函数不可以返回不由const修饰的指向私有成员数据的引用或者指针。
41、包含语句应该排序并分组。排序时,按照其在系统中的层次位置,较低层的包含语句在前。用空行分隔分组的包含语句。
包含文件的路径中,不要含有绝对路径。
#include <iostream> #include <sstream> #include <cmath> #include <cstdlib> #include "NewRational.h"
42、包含语句必须放在源文件的顶部,放在其他位置也许会引起预期之外的其他副作用