/*1,视C++为一个语言联邦-----------------------------------------------------------------*/
//<1>:C++是以C为基础,区块(blocks)、语句(statements)、预处理(preprocessor)、
// 内置数据类型(built-in data types)、 数组(arrays)、指针(points)等统统来自于C
//<2>:C++又包含了新的,析构函数和构造(classess)、封装(encapsulation)、继承(inheritance)、
/ /多态(polymorphism)、虚函数(动态绑定)等等
//<3>:Template C++这是C++的泛型编程,是整个C++用的最多的地方
//<4>:STL是Template的程序库,它对容器,迭代器,算法,函数对象的规约有极佳的紧密配合与协调
/*2,尽量以const、enum、inline替换#define;用编译器替代预处理器---------------------------*/
#define ASPECT_RATIO 1.653
const double AspectRation = 1.653 //用常量替换上面的宏定义
const std::string authorName("Scott Meyers") //字符串常量定义
class GamePlayer //定义class的专属常量
{
private:
static const int Num; //常量声明式
enum{NumTurns = 5}; //使用枚举,取枚举的地址是不合法的
int scores[NumTurns]; //使用该常量
}
const int GamePlayer::Num = 5; //常量的定义,在实现文件中实现,不是在头文件中
#define CALL_WITH_MAX(a, b) f((a)>(b) ? (a) : (b)) //函数宏定义操作
template <typename T> //使用类内联函数来替代
inline void callWithMax(const T&a, const T &b)
{
f(a > b ? a : b);
}
/*3,尽可能使用const--------------------------------------------------------------------*/
//<1>,如果关键字const出现在星号的左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;
// 如果出现在星号两边,表示被指物和指针两者都是常量
//<2>,const修饰函数返回值
//<3>,const修饰成员函数,1:它们使class接口比较容易被理解,得知那个函数可以改动对象内容而那个函数不行,很重要
// 2:它们使"操作const对象"成为可能,改善C++效率的根本方法以pass by referecnt-to-const(引用方式)传递对象
// 3:两个成员函数如果只是常量性不同,可以被重载
char greeting[] = "Hello"
const char *p = greeting; //数据是const,指针不是const
char * const p = greeting; //数据不是const,指针是const
const char * const p = greeting; //数据是const,指针是const
vector<int> vec;
const vector<int>::iterator iter = vec.begin(); //iter的作用像个 T* const
*iter = 10; //没有问题
++iter; //错误 iter是const
vector<int>::const_iterator cIter = vec.begin(); //cIter的作用像个const T*
*cIter = 10; //错误*cIter是const
++cIter; //没有问题
class Rational{};
const Rational operator* (const Rational &1hs, const Rational &rhs); //const修饰函数返回值
Rational a, b, c;
(a*b) = c; //不合法
class TextBlock{
public:
const char & operator[](std::size_t position) const //const修饰类成员函数
{
return text[position]; //const对象
}
char & operator[] (std::size_t position)
{
return text[position]; //non-const对象
}
private:
std::string text;
}
void print(const TextBlock &ctb) //此函数ctb是const
{
std::cout << ctb[0]; //调用const TextBlock::operator[]
}
TextBlock tb("Hello");
const TextBlock ctb("World");
tb[0] = 'x'; //合法
ctb[0] = 'x'; //错误
/*4,确定对象被使用前已先被初始化---------------------------------------------------------*/
//<1>,确保每一个构造函数都将对象的每一个成员初始化
//<2>,赋值和初始化是有区别的
//<3>,成员初始化的顺序总是以其声明次序被初始化
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;
}
//这些都是赋值
ABEntry::ABEntry(const std::string &name, const std::string &address, const std::list<PhoneNumber> &phones)
{
theName = name;
theAddress = address;
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),numTimeConsulted(0)
{
}
//不同编译顺序带来的问题: 如果Directory比FileSystem先编译将会带来不可预知的问题
class FileSystem{
public:
std::size_t numDisks() const;
}
extern FilesSystem tfs; //给客户使用
class Directory{
public:
Directory(params);
}
Directory::Directory(params)
{
std::size_t disks = tfs.numDisks(); //调用tfs对象
}
//解决问题方法:使non-local static 对象被 static对象替代
//static: 1,局部静态变量:在初次运行时进行初始化工作,且只初始化一次;
// 2,全局静态变量:用来表示 不能被其它文件访问的全局变量和函数
// 3, 静态数据成员/成员函数
class FileSystem{}
FileSystem & tfs()
{
static FileSystem fs;
return fs;
}
class Directory{}
Directory::Directory(params)
{
std::size_t disks = tfs().numDisks();
}
/*5,C++会默默编写并调用哪些函数----------------------------------------------------------*/
//定义一个空类
class Empty{
};
//编译器会默认声明的一些函数
class Empty{
public:
Empty() {} //default构造函数
Empty(const Empty &rhs){} //拷贝构造函数
~Empty() {} //析构函数
Empty & operator= (const Empty &rhs) {} //拷贝赋值操作符
};
Empty e1; //default构造函数
Empty e2(e1); //拷贝构造函数
e2 = e1; //赋值函数
/*6,若不想使用编译器自动生成的函数,就应该明确拒绝------------------------------------------*/
//阻止调用:拷贝构造函数,赋值函数的方法是声明函数为private而不进行定义
class HomeForSale{
public:
private:
HomeForSale(const HomeForSale &); //只有声明,不定义
HomeForSale & operator=(const HomeForSale &);
}
/*7,为多态基类声明virtual析构函数--------------------------------------------------------*/
//<1>,虚函数实现了C++的多态性;基类为虚函数派生类自动为虚函数
class A
{
virtual void display()
{
cout << "This is A";
}
}
class B : public A
{
void display()
{
cout << "This is B";
}
}
class C : public A
{
void display()
{
cout << "This is C";
}
}
void main(void)
{
A x1;
B x2;
C x3;
A *p = &x1;
p->display; //输出 This is A
p = &x2;
p->display; //输出This is B
p = &x3;
p->display; //输出This is C
}
//非基类virtual删除出错
class TimeKeeper
{
public:
TimeKeeper();
~TimeKeeper();
};
class AtomicClock: public TimKeeper{};
AtomicClock *aClock = new AtomicClock;
TimeKeeper *Clock = aClock;
delete Clock; //出错
class TimeKeeper
{
public:
TimeKeeper();
virtual ~TimeKeeper();
};
class AtomicClock: public TimKeeper{};
AtomicClock *aClock = new AtomicClock;
TimeKeeper *Clock = aClock;
delete Clock; //正确
/*8,别让异常逃离析构函数--------------------------------------------------------------*/
/*9,绝对不在构造和析构过程中调用virtual函数---------------------------------------------*/
/*10,令operator=返回一个 reference to *this------------------------------------------*/
// x=y=z=15; 从右赋值
class Widget
{
public:
Widget & operator += (const Widget &rhs)
{
return *this;
}
};