本书总共分7个章节。
算是很基础的东西,理解起来没什么难度,算是对C++基础的复习,所以有基础的同学应该看的很快。
对我来说读这一部分的收获就是重新理解static关键字、inline内联函数、函数指针。
主要就是介绍STL中的容器(vector、list、set、map),以及作用于这些容器的泛型算法,容器一般都是直接拿来用,这章则更偏向于底层的介绍,说实话除了迭代器有了点深入的理解外,其他还是不太懂。
这两章可以说是我初读本书收获最大的部分,其实很大一部分我写的代码都是基于对象的编程风格,比如最多写几个类,封装几个函数,给其他类调用,最多写个类之间的继承,类之间仅仅是"is-a-kind-of"的关系。这种是基于对象(object-based)的编程。
那到底什么才是面向对象的编程呢?书中的解释是:面向对象编程的两个主要特性是:继承(inheritance)和多态(polymorphism)。继承不用多说,很容易理解 ,就是让我们可以定义一些相互关联的类,并共享共同的接口。那么多态呢?书里说多态则让我们得以用一种与类型无关(type-independent)的方式来操作这些类对象,看完后面的例子,其实就是我们使用派生类的时候,是让基类的指针指向派生类的对象。这是面向对象的动态绑定(dynamic binding)机制,需要用到虚函数来实现。借用书中图书馆的例子来说明一下。大致结构是基类LibMat、派生类Book、Book的派生类AudioBook。
#include
#include
#include
using namespace std;
class LibMat
{
public:
LibMat();
virtual ~LibMat();
virtual void print() const
{
cout << "父类LibMat的print()函数被调用\n";
}
};
LibMat::LibMat()
{
cout << "父类LibMat的默认构造函数被调用!\n";
}
LibMat::~LibMat()
{
cout << "父类LibMat的默认析构函数被调用!\n";
}
class Book:public LibMat
{
public:
Book(const string &title,const string &author)
:_title(title),_author(author)
{
cout << "Book::Book(" <<_title << "," << _author << ") 构造函数!\n";
}
virtual ~Book()
{
cout << "Book::~Book() 析构!\n";
}
virtual void print() const{
cout << "Book::print() --I am a Book object!\n"
<< "My title is:" << _title << '\n'
<< "My author is:" << _author << endl;
}
const string title() const { return _title; }
const string author() const { return _author;}
protected:
string _title;
string _author;
};
class AudioBook:public Book
{
public:
AudioBook(const string &title,const string &author,const string &narrator)
:Book(title,author),_narrator(narrator)
{
cout << "AudiBook::AudiBook(" << _title
<< "," << _author
<< "," << _narrator
<< ") construcor\n";
}
~AudioBook()
{
cout << "AudioBook::~AudiBook() destructor!\n";
}
virtual void print() const{
cout << "AudioBook::print() --I am an AudiBook object!\n"
<< "My title is: " << _title << '\n'
<< "My author is:" << _author << '\n'
<< "My narrator is:" << _narrator << endl;
}
const string& narrator()const { return _narrator; }
protected:
string _narrator;
};
可以看到每个类都有一个print()函数,用来输出一些基本信息,基类LibMat的print打印一条语句,表明是基类的print被调用了,Book类的print打印的是书名和作者,AudioBook类打印的是书名、作者和朗读者。下面看看用法
假设我定义一个函数print()用来调用这些类,print()的参数是LibMat类的一个对象。
void print(const LibMat &mat)
{
cout << "在全局print()函数中打印mat对象的print函数!\n";
mat.print();
}
int main()
{
cout << "\n" << "Createing a LibMat object to print()\n";
LibMat libmat;
print(libmat);
}
第一次我调用基类LibMat,可以看到基类的print()被正常调用。
第二次我调用Book类,但是print(const LibMat &mat)的定义还是不变。
int main()
{
//cout << "\n" << "Createing a LibMat object to print()\n";
//LibMat libmat;
//print(libmat);
cout << "\n" << "Createing a Book object to print()\n";
Book b("The Castle", "Franz Kafka");
print(b);
}
可以看到,
我们并没有把非成员函数改成print(const Book &mat),但是程序还是正确调用了Book类的print()函数,输出了书名和作者。
第三次我调用AudioBook,print(const LibMat &mat)的定义还是不变。
int main()
{
//cout << "\n" << "Createing a LibMat object to print()\n";
//LibMat libmat;
//print(libmat);
//cout << "\n" << "Createing a Book object to print()\n";
//Book b("The Castle", "Franz Kafka");
//print(b);
//
cout << "\n" << "Createing a AudioBook object to print()\n";
AudioBook ab("The Castle", "Franz Kafka","Kenneth Meyer");
print(ab);
}
同理,
我们不用把非成员函数改成print(const AudioBook &mat),也能得到正确的输出结果。
这就是本节一开始提到的多态则让我们得以用一种与类型无关(type-independent)的方式来操作这些类对象。
这一章的小建议,读的时候可以反复读几遍,第一节的概念一开始看起来可能有点抽象,等看完后面的代码再回头看概念会有新的理解。
这一章看的时候真的很头大,反复读了好几遍还是没怎么看懂,特别是类模板的部分,我真的是大声读出来的,因为看着看着思维就飘了。然而还是没怎么看懂。只能作为遗留,下次再看了。
这一章很简短,讲的就是程序的异常捕捉处理机制,算是很常见的用法,没理解的地方是局部资源管理。
不建议初学者使用,否则会看的一头雾水。即使有一定C++基础的同学也要慎重,就我读下来的感觉是,逻辑上跟一般的理解方式不同,比如有很多知识点直接拿来用,然后在后面的章节才会有详细解释,这就需要我们再跳回之前的地方再细看,也就是说需要我们前后比对着看,很多情况下第一遍看是一头雾水的,莫名其妙来段代码就开始讲。所以给想学习这本书的同学两点建议:
(1)最好使用纸质书,这样前后翻阅起来方便。当然也可能是我个人用不惯电子书看这类技术类的书籍。
(2)第一遍可能读不懂,没关系,硬着头皮看下去,然后再回头看前面不懂的地方,如果还不懂,但是对于后面的理解没有太大的影像,那就略过,如果跟后面知识点的理解关系很大,那就只能多读几遍了。
之后会再读一遍,也可能不止一遍,重点就在自己之前没读懂的地方啦。学习嘛,无非就是看看书,自己思考思考,然后在工作中一点点实践,然后再回头看看书,如此循环往复,以前不懂的地方可能就会有一些突破,懂的地方也可能会有新的理解。这就是一个学而思、思而学的过程,慢慢的内化成自己的知识。