Essential C++濃縮筆記(四)——基於對象的編程風格

來自Stanley B.Lippman的《Essential C++》第四章重要內容的總結,第四章目錄:

1、實現Class

Class聲明 

只有前置聲明之後 纔能有類指針的定義 或者 以此Class作爲數據類型

calss Stack;                   //聲明
...
Stack *pt = 0;                //定義一個類指針
void pocess(const Stack&);    //以Stack作爲數據類型

Class定義

所有member function都必須在Class主體內進行聲明,至於是否要同時進行定義,可以自由定義。如果定義在Class以外,用": :" 表示xx函數是xx類的一個member

 

2、 構造函數(constructor)和折構函數(destructor)

構造函數是用來初始化 date member的函數,constructor的函數名稱必須與Class名稱相同,沒有返回值,可以被重載。

定義方法一:

class Triangular {
public:
	Triangular();		//default constructors
	Triangular(int len);		
	Triangular(int len, int beg_pos);
};

如果構造函數沒有任何參數,有兩種可能:

1、它不接受任何參數,有可能有參數但是參數在這個構造函數內已經被寫死,不允許更改

2、爲每個參數提供了默認值,這種有默認值的構造函數也可以作爲default 構造函數

定義方法二:

成員初始化列表,欲賦值給member的數值被放在member名稱後面的小括號中。

Trianglular::Triangular(int len, int bp):_name("Triangular")
{
    _length = len > 0 ? len : 1;
    _beg_pos = bp > 0 ? bp : 1;
    _next = _beg_pos - 1;
}

 折構函數 與構造函數相對,一旦某個class提供有destructor,當其object結束生命時,便會自動調用destructor處理善後。主要用來釋放在constructor中或者對象生命週期中分配的資源。

 

3、mutable和const

對於const參數,編譯器必須保證參數在程序運行過程中不會被修改。

凡是在class主體以外定義的,如果是一個const member function,那就必須同時在聲明與定義中指定const。

class Triangular{
public:
    int elem(int pos) const;    //聲明
...
};

int elem(int pos) const{
    return _elem[pos-1];        //定義時也要指定const
}

 mutable

如果_next被表示爲mutable,那麼可以宣稱,對_next所做的改變不會破壞class object的常量性。

 

4、this指針

this指針在member function內用來指向其調用者,它可以讓我們訪問調用者的一切,下面提供copy函數的定義及調用。

Triangular& Triangular::copy(const Triangular &rhs) {
	_length = rhs._length;
	_begin_pos = rhs._begin_pos;	
	return *this;
}


tr1.copy(tr2);                    //調用,將tr2複製給tr1

5、靜態類成員

靜態成員數 static date member

靜態成員數用來表示唯一的、可共享的member。它可以在同一類的所有對象中被訪問。static date member在定義的時候它的名稱必須附上class scope運算符。

class Triangular{
public:
//...
private:
    static vector<int>_elems;        //static data member聲明
};

//以下代碼放在程序代碼文件中,例如Triangular.cpp
vector<int>Triangular::_elems;        //絕對不能丟,否則無法被編譯器實現

靜態成員函數

一般情形下,member function必須通過其類的某個對象來調用,但是對於靜態成員函數可以直接調用,前提是利用class scope說明基於的類對象,且靜態成員函數沒有訪問任何的non-static member。

Triangular tri;                        //定義一個Triangular對象,名字是tri
bool is_elem = tri.is_elem(ival);      //調用function member

bool is_elem = Triangular::is_elem(ival); //如果is_elem是靜態成員函數,可以直接調用
static bool is_elem(int);                //在class內的函數聲明

6、運算符重載

 像定義member function那樣來定義運算符,唯一的差別是它不用指定名稱,只需要在運算符前加上關鍵字operator即可。


class Triangular_iterator{
public:
    bool operator==(const Triangular_iterator&) const;    //運算符重載聲明
...
};

inline  bool operator==(const Triangular_iterator &rhs) const{
    return _index==rhs._inedx;                            //定義
}

if(trian1 == trian2)...                                    //調用

運算符重載規則:

1、不能引入新的運算符;2、運算符函數列表中,必須至少有一個參數爲Class類型;3、優先級不可改變 

 

7、訪問類的私有成員

任何類都可以將其他function或class指定friend,friend具備與class member function相同的訪問權限,可以訪問class 的私有成員。只需要在某個函數的原型上加上關鍵字friend,就可以將它聲明爲某個class的friend。

爲了讓定義成功通過編譯,必須在聲明之前,提供類的定義(使用的那個類),否則無法確定函數原型是否正確。

也可以把整個類作爲另一個類的friend

class Triangular{
    friend class Triangular_iterator;
    ...
};

 如果能通過public member function來訪問私有成員,那麼就不必通過建立friend 關係。

 

8、function object

function object是一種提供有function call運算符“()”的class

bool operator()(int value) const;        //聲明

bool Lessthan::operator()(int value) const //定義
{
	return value < _val;
}

    
for (int i = 0; i < vec.size(); i++)     //調用
{
	if (lt(vec[i]))		
	count++;
}

通常會把function object當作參數傳給泛型算法 

vector<int>::const_iterator iter = vec.begin();
vector<int>::const_iterator it_end = vec.end();
os << "elements less than" << lt.comp_val() << endl;
while ((iter = find_if(iter, it_end, lt)) != it_end)	//把function object當作參數傳給泛型算法
{
	os << *iter << ' ';
	++iter;
}

 

 

遇到的問題及總結

1、記錄程序運行的時間(秒及毫秒)

//程序運行時間(秒)
#include<ctime>

clock_t startTime, endTime;
startTime = clock();            //計時開始
...
endTime = clock();             //計時結束
cout << "time: " <<(double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;

//程序運行時間(毫秒)

#include<ctime>
DWORD startTime = GetTickCount();//計時開始
....
DWORD endTime = GetTickCount();//計時結束
cout << "The run time is:" << endTime - startTime << "ms" << endl;

2、註釋要規範,美觀,體現結構

https://blog.csdn.net/weixin_42488570/article/details/80760849

兩張註釋對比

一)基本沒有註釋

 二)結構清晰,明白易懂

 

3、 錯誤LNK2001無法解析的外部符號

參考這篇文章:https://blog.csdn.net/aaron121211/article/details/50384289

處理函數有可能沒有被實現,成員數也有可能沒有被實現,比如static vector<int> _elems,除了在class內的申明,還要在cpp文件內定義(實現)!

 

發佈了31 篇原創文章 · 獲贊 143 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章