C++書籍閱讀系列:《Essential C++》初讀

本書介紹

本書的作者是Stanley B.Lippman,也是《C++ primer》的作者,我看的是侯捷老師翻譯的中文版。相對於《C++ primer》的大部頭,這本書可以說是短小精悍了,除去附錄就只有200頁左右了。但是個人覺得涵蓋的知識點還是不太容易理解的,比如泛型編程和類模板章節。

自我收穫和不足

本書總共分7個章節。

第一章(C++編程基礎)、第二章(面向過程的編程風格)

算是很基礎的東西,理解起來沒什麼難度,算是對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 <iostream>
#include <stdlib.h>
#include <string>
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)的方式來操作這些類對象

這一章的小建議,讀的時候可以反覆讀幾遍,第一節的概念一開始看起來可能有點抽象,等看完後面的代碼再回頭看概念會有新的理解。

第六章(以template進行編程)

這一章看的時候真的很頭大,反覆讀了好幾遍還是沒怎麼看懂,特別是類模板的部分,我真的是大聲讀出來的,因爲看着看着思維就飄了。然而還是沒怎麼看懂。只能作爲遺留,下次再看了。

第七章(異常處理)

這一章很簡短,講的就是程序的異常捕捉處理機制,算是很常見的用法,沒理解的地方是局部資源管理。

讀者建議

不建議初學者使用,否則會看的一頭霧水。即使有一定C++基礎的同學也要慎重,就我讀下來的感覺是,邏輯上跟一般的理解方式不同,比如有很多知識點直接拿來用,然後在後面的章節纔會有詳細解釋,這就需要我們再跳回之前的地方再細看,也就是說需要我們前後比對着看,很多情況下第一遍看是一頭霧水的,莫名其妙來段代碼就開始講。所以給想學習這本書的同學兩點建議:
(1)最好使用紙質書,這樣前後翻閱起來方便。當然也可能是我個人用不慣電子書看這類技術類的書籍。
(2)第一遍可能讀不懂,沒關係,硬着頭皮看下去,然後再回頭看前面不懂的地方,如果還不懂,但是對於後面的理解沒有太大的影像,那就略過,如果跟後面知識點的理解關係很大,那就只能多讀幾遍了。

小結

之後會再讀一遍,也可能不止一遍,重點就在自己之前沒讀懂的地方啦。學習嘛,無非就是看看書,自己思考思考,然後在工作中一點點實踐,然後再回頭看看書,如此循環往復,以前不懂的地方可能就會有一些突破,懂的地方也可能會有新的理解。這就是一個學而思、思而學的過程,慢慢的內化成自己的知識。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章