Effectice C++01
条款01:视C++为一个语言联邦
- C
区块(blocks)、语句(statements)、预处理(preprocessor)、内置数据类型(built-in data types)、数组(arrays)、指针(pointers)
- Object-Oriented C++
classes(包括构造和析构函数)、封装(encapsulation)、继承(inheritance)、多态(polymorphism)、virtual(动态绑定)
- Template
泛型编程、模板元编程
- STL
容器、迭代器、算法、函数对象
条款二:尽量以const、enum、inline、替换#define
以编译器替换预处理器
#define ASPECT_ROTIO 1.653 // 可能并未记录到符号表 获取编译错误信息会提到 1.653
// 目标码会出现多份1.653
const double AspectRotio = 1.653
// 常量指针
const char* const authorName = "Scott Meyers"
// class 专属常量
class GamePlayer {
private:
// 通常需要在外面有定义式
// static 且为整数类型 int char bool 只要不取它们的地址,可以提供声明式而无需提供定义式
static const int NumTurn = 5; //声明常量=======================================
int scores[NumTUr];
}
const int GamePlayer::Numturns; // Numturns的定义 放进一个实现文件
class GamePlayer {
private:
enum {
NumTurns = 5}; // the enum hack 无法取地址
int score[NumTruns];
}
- 对于单纯常量,最好以const对象或enum替换#define
- 对于形似函数的宏,最好改用inline函数替换#define
条款03:尽可能使用const
STL迭代器以指针为根据塑模出来,所以迭代器的作用就像一个T*指针
。声明迭代器为const对象就像声明指针为const一样(即声明一个T* cosnt
指针)——不得指向不同的东西,它所指的东西的值是可以改变的。
const T*
指针 => const_iterator
const 可以和函数返回值、各参数、函数自身(成员函数)产生关联
const和non-const成员函数中避免重复
令non-const版本调用const版本可避免代码重复。
class TextBlock {
public:
const char& operator[] (std::size_t position) const
{
//.....
return text[position];
}
char& operator[] (std::size_t position) {
return
const_cast<char&>( // 返回const对象 转化为非const对象
static_cast<const TextBlock&>(*this) // 转化为const对象 为调用cosnt函数
[position]
);
}
}
条款04:确定对象使用之前已被初始化
C part of C++ 不保证发生初始化
array(来自C part of C++)不保证其内容被初始化, vector(STL part of C++)却有此保证
除内置类型,初始化责任落在构造函数(constructors)身上
别混淆了赋值(assignment)和初始化(initialization)
class PhoneNumber{
//... };
class ABEntry {
// 通讯簿
public:
ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones);
private:
std::string theName;
std::string theAddress;
std::list<PhoneNumber> thePhones;
int numTimesConsulted;
};
// 首先调用default构造函数为theName、theAddress和thePhones设初值
// 然后立即再对他们赋予新值 浪费了default构造函数做的一切
AbEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones);
{
theName = name; // 这些都是赋值(assignments)
theAddress = address; // 而非初始化 (initializations)
thePhones = phones;
numTimesConsulted = 0; // 内置对象,初始化和赋值的成本相同
}
AbEntry::ABEntry(const std::string& name, const std::string& address,
const std::list<PhoneNumber>& phones) // 现在都是初始化
:theName(name),
theAddress(address),
thePhones(phones),
numTimesConsulted(0)
{
}
初始化次序:
base classes更早与其derived被初始化
class的成员变量总是以其声明的次序初始化
static对象,其寿命从被构造出来直到程序结束为止
函数内的static对象称为local static对象,其它的static对象称为non-local-static对象
class FileSystem {
public:
std::size_t numDisks() const;
//...
};
static FileSystem tfs; //预备给客户使用的对象
class Directory {
public:
Directiry(params);
// ...
};
Directory::Directory(params