将构造函数声明为explicit,可阻止被用来执行隐式类型转换,仍可被用来进行显示类型转换
class C{
public:
explicit C(int x);
}
Accustoming Yourself to C++ #
1.View C++ as a federation of languages #
- C
- Object-Oriented C++
- Template C++
- STL
2.Perfer consts,enums,and inlines to#defines #
一旦宏被定义,在其后的编译过程中一直有效,除非在某处被#undef
const double AspectRatio = 1.653;
const char* const authorName = "Scott Meyers";
const std::string authorName("Scott Meyers");
对于单纯常量,最好以const对象或者enums替换#defines
class GamePlayer{
private:
static const int NumTurns = 5;//新一点的编译器才支持声明时定义
int scores[NumTurns];
}
class GamePlayer{
private:
enum{ NumTurns = 5};
int scores[NumTurns];
}
对于形似函数的宏(macros),最好改用inline函数替换#defines
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b)) //不建议
//建议使用inline,宁可用编译器替换预处理器
template<typename T>
inline void callWithMax(const T& a,const T& b)
{
f(a > b ? a : b);
}
3.Use const whenever possible #
char greeting[] = "Hello";
const char* p = greeting;//non-const pointer,const data
char* const p = greeting;//const pointer,non-const data
const char* const p = greeting;//const pointer,const data
迭代器中使用const
std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin();
*iter = 10;
++iter;//错误
std::vector<int>::const_iterator cIter = vec.begin();
*cIter = 10;//错误
++cIter;
4.Make sure that objects are initialized before they’re used #
- 永远在使用对象之前 先将它初始化
- 为内置对象进行手工初始化,因为C++不保证初始化它们
- 确保每一个构造函数都将对象的每一个成员初始化
- 总是使用成员初始列(member initialization list)
- 当你在成员初始值列中条列各个成员时,最好总是以其声明次序为次序
ABEntry::ABEntry()
:theName(),//调用theName的default构造函数
theAddress(),
the Phones(),
numTimesConsulted()
{
}
- 为免除“跨编译单元之初始化次序问题”,主以local static 对象替换non-local static 对象
所谓编译单元(translation unit)是指产出单一目标文件(single object file)的那些源码
non-local static 对象:global或位于namespace作用域内,抑或在class内或file 作用域内被声明为static的对象
如果某编译单元内的某个non-local static 对象的初始化动作使用了另一编译单元内的某个non-local static 对象,它所用到的这个对象可能尚未被 初始化,因为C++对“定义于不同编译单元内的non-local static 对象”的初始化次序并无明确定义