第一章 計(jì)算機(jī)與C++編程簡介
C++程序6個(gè)階段
編程 ->預(yù)處理->編譯->連接->裝入->執(zhí)行
1.程序在編譯器中生成源程序并存盤
2.預(yù)處理程序處理代碼
3.編譯器建立目標(biāo)程序并存盤
4.連接器將目標(biāo)碼與庫連接,生成a.out文件并將其存盤
5.裝入器把程序放進(jìn)內(nèi)存中
6.cpu取出每條指令并執(zhí)行Cin:標(biāo)準(zhǔn)輸入流
Cout:標(biāo)準(zhǔn)輸出流
<< :流插入運(yùn)算符
cout << "welcome to c++ ! \n";
>> :流讀取運(yùn)算法
endl
end line的縮寫,endl輸出一個(gè)換行符,然后刷新輸出緩沖區(qū),即在一些系統(tǒng)中,輸出暫時(shí)在機(jī)器中緩存,等緩沖區(qū)滿時(shí)再打印到屏幕上,endl強(qiáng)制立即輸出到屏幕上。
cout << "sum is" << sum << endl;
使用多個(gè)流插入運(yùn)算符稱為連接,鏈接或連續(xù)使用流插入操作。
- use namespace std;
指定用std名稱空間(namespace),我們可以將我們的所有類和函數(shù)放在名字空間detail中。
如果通過use namespace std聲明,我們在使用輸出流時(shí)就可以這樣寫:
cout << "sum is" << sum << endl;
否則我們需要在cout前加上std::
std::cout << "sum is" << sum << endl;
意思是使用std空間內(nèi)命名為cout的函數(shù)
C++標(biāo)準(zhǔn)中引入命名空間的概念,是為了解決不同模塊或者函數(shù)庫中相同標(biāo)識符沖突的問題。有了命名空間的概念,標(biāo)識符就被限制在特定的范圍(函數(shù))內(nèi),不會引起命名沖突。最典型的例子就是std命名空間,C++標(biāo)準(zhǔn)庫中所有標(biāo)識符都包含在該命名空間中。
如果確信在程序中引用某個(gè)或者某些程序庫不會引起命名沖突(即庫中的標(biāo)識符不會在程序中代表其他函數(shù)名稱),那么可以通過using操作符來簡化對程序庫中標(biāo)識符(通常時(shí)函數(shù))的使用,例如:using namespace std;那么就可以不用在標(biāo)識符在前綴std::來使用C++標(biāo)準(zhǔn)庫庫中的函數(shù)了
- 未初始化變量會包含未定義值,為該變量保有內(nèi)存地址中最后存放的值
第二章 控制結(jié)構(gòu)
- static_cast <float> ( ) 強(qiáng)制類型轉(zhuǎn)換運(yùn)算附
average = static_cast <float> (total) / gradeCounter;
- setprecision( ) 設(shè)置精度,即打印小數(shù)點(diǎn)后幾位。需要導(dǎo)入iomanip.h
#incloud <iomanip.h>
cout << "class average is" << setprecison(2) << setiosflags ( ios :: flxed | ios :: showpoint ) << average << endl;
setiosflags ( ios :: flxed | ios :: showpoint )表示設(shè)置兩個(gè)輸出格式選項(xiàng),ios :: flxed表示使浮點(diǎn)數(shù)值以浮點(diǎn)格式(而不是科學(xué)技術(shù)法)輸出。即使是整數(shù),ios::showpoint選項(xiàng)也會強(qiáng)制打印小數(shù)點(diǎn)和尾部0。
表示float變量average打印小數(shù)點(diǎn)后兩位,需導(dǎo)入iomanip.h。如果不指定精度,則浮點(diǎn)數(shù)值通常輸出六位精度(默認(rèn)精度)
a+=1, a++,++a 有些編譯器在用縮寫賦值運(yùn)算符時(shí)能產(chǎn)生運(yùn)行速度更快的代碼。
如果for結(jié)構(gòu)體中有一條語句,可以不用花括號包裹代碼。如果有多條語句,則應(yīng)把語句體放在花括號中。
最新ANSI/ISO C++草案標(biāo)準(zhǔn)實(shí)際上指定iostream.h和其他標(biāo)準(zhǔn)頭文件不需要后綴.h,如iostream。
setw()用來控制輸出間隔。
setiosflags(ios::left)指定輸出的值為左對齊。
cin.get()函數(shù)表示從鍵盤讀取一個(gè)字符。
while((grade = cin.get()) != EOF) 我們用EOF(通常取值為-1)作為標(biāo)記值。EOF是<iostream.h>頭文件中定義的符號化整數(shù)常量。如果grade的取值為EOF,則程序終止。
測試符號化常量EOF而不是測試-1能使程序更容易移植。ANSI標(biāo)準(zhǔn)要求EOF取負(fù)整數(shù)值,但不一定是-1。這樣,EOF在不同程序中可能取不同的值。
第三章 函數(shù)
sqrt ()計(jì)算括號中所包含數(shù)字的平方根
int maximum (int,int, int); 函數(shù)聲明規(guī)則
rand ( ) ;
多次打印的數(shù)值順序與第一次相同,怎么能算是隨機(jī)數(shù)呢?其實(shí)這種可重復(fù)性是rand函數(shù)的一個(gè)重要特性。調(diào)試程序時(shí),這種可重復(fù)性提供了證明修改后程序能正確工作的關(guān)鍵。一旦程序進(jìn)行徹底調(diào)試之后,就可以調(diào)整為在每次執(zhí)行程序時(shí)產(chǎn)生不同的隨機(jī)數(shù)系列。這個(gè)過程稱為隨機(jī)化,是用標(biāo)準(zhǔn)庫函數(shù)srand完成的。srand函數(shù)取一個(gè)unsigned類型的整數(shù)參數(shù)并內(nèi)嵌rand函數(shù),就可以在每次執(zhí)行程序時(shí)產(chǎn)生不同的隨機(jī)數(shù)系列。(此處如果需要,請百度多了解一下)
srand(time ( 0 ));
srand函數(shù)只要在程序中調(diào)用一次即可得到所需的隨機(jī)化結(jié)果,多次調(diào)用是多余的,會降低程序性能。enum Status {CONTINUS, WON, LOST};
作為用戶自定義類型名的標(biāo)示符,其第一個(gè)字母應(yīng)大寫。存儲類說明符
auto :局部變量默認(rèn)為自動(dòng)存儲類,在進(jìn)入聲明塊時(shí)生成并在退出這個(gè)塊時(shí)刪除。
register : 讓編譯器在計(jì)算器的高速硬件寄存器中而不是在內(nèi)存中保存這個(gè)變量,這樣可以消除從內(nèi)存向寄存器裝入變量和將結(jié)果返回內(nèi)存中的重復(fù)開銷。
extern : 對于一個(gè)全局變量,它既可以在本源文件中被訪問到,也可以在同一個(gè)工程的其它源文件中被訪問(只需用extern進(jìn)行聲明即可)。
static : 一般情況下,對于局部變量是存放在棧區(qū)的,并且局部變量的生命周期在該語句塊執(zhí)行結(jié)束時(shí)便結(jié)束了。但是如果用static進(jìn)行修飾的話,該變量便存放在靜態(tài)數(shù)據(jù)區(qū),其生命周期一直持續(xù)到整個(gè)程序執(zhí)行結(jié)束。但是在這里要注意的是,雖然用static對局部變量進(jìn)行修飾過后,其生命周期以及存儲空間發(fā)生了變化,但是其作用域并沒有改變,其仍然是一個(gè)局部變量,作用域僅限于該語句塊。
在用static修飾局部變量后,該變量只在初次運(yùn)行時(shí)進(jìn)行初始化工作,且只進(jìn)行一次。
了解更多 : http://developer.51cto.com/art/201104/256820.htm
inline
說明這個(gè)函數(shù)是內(nèi)聯(lián)的,在編譯過程中內(nèi)聯(lián)函數(shù)會直接被源代碼替換,提高執(zhí)行效率 如果類中的某個(gè)函數(shù)會被調(diào)用很多次或者放在循環(huán)中,那么建議將這個(gè)函數(shù)聲明為內(nèi)聯(lián),可以提高程序的運(yùn)行效率關(guān)鍵字const
- void f (const int i) { i=10;//error! } 如果在函數(shù)體內(nèi)修改了i,編譯器就會報(bào)錯(cuò)
- 要指定引用常量,在參數(shù)聲明的類型說明符前加上const限定符。
按值調(diào)用傳遞的一個(gè)缺點(diǎn)是,如果傳遞較大的數(shù)據(jù)項(xiàng)目,則復(fù)制這個(gè)數(shù)據(jù)可能要占用相當(dāng)長的執(zhí)行時(shí)間。按引用調(diào)用對性能有利,因?yàn)樗藦?fù)制大量數(shù)據(jù)的開銷,但是其安全性較差,因?yàn)楸徽{(diào)用函數(shù)能夠直接訪問和修改調(diào)用者的數(shù)據(jù)。
& : 在函數(shù)原型中概參數(shù)類型后面加上&,即可按引用調(diào)用參數(shù)。
為了獲得程序的清晰性和高性能,許多c++程序猿喜歡通過指針將可修改參數(shù)傳遞給函數(shù)(&),不可修改的小參數(shù)按值調(diào)用傳遞,而不可修改的大參數(shù)用常量引用傳遞給函數(shù)(const) 。
int boxVolume( int length = 1, int width = 1, int height = 1);
為函數(shù)的參數(shù)添加默認(rèn)值。使用默認(rèn)值能簡化函數(shù)調(diào)用,但有些程序猿認(rèn)為顯示指定所有參數(shù)更清楚。一元作用域運(yùn)算符 ::
如果有兩個(gè)同名變量,一個(gè)是全局的,一個(gè)是局部的,那么局部的變量在其作用域擁有較高的優(yōu)先權(quán),全局變量則被屏蔽。那如果我希望在局部變量的作用域里使用全局變量怎么辦,這時(shí)就要用到::作用域運(yùn)算符了。函數(shù)重載
c++允許定義多個(gè)同名函數(shù),只要這些函數(shù)有不同的參數(shù)集(至少有不同類型的參數(shù))。
int square ( int x);
double square (double y);
重載是通過簽名進(jìn)行區(qū)別,簽名是函數(shù)名和參數(shù)類型的組合。編譯器用參數(shù)格式 和類型編碼每個(gè)函數(shù)表示符,以確保類型安全連接。重載函數(shù)可以有不同返回類型,但必須有不同參數(shù)表。
public @nothing2$qzcipfpd
public @nothing1$qifzcpi
- 函數(shù)模版
重載函數(shù)通車用于不同數(shù)據(jù)類型用不同程序邏輯進(jìn)行類似的操作。如果每種數(shù)據(jù)類型的程序邏輯有操作相同,那么用函數(shù)模版完成這項(xiàng)工作更加簡潔和方便。所有的模版定義都是以關(guān)鍵字template開頭,之后是用尖括號括起來的形式參數(shù)表。
template <class T>
T maximum (T value1, T value2, T value 3){
...
}
第四章 數(shù)組
如果初始化的元素比數(shù)組中的元素少,則奇遇元素自動(dòng)初始化為0。
"hello"之類的字符串其實(shí)就是一個(gè)字符數(shù)組。
char string[] = {'f','i','r','s','t','\0'};
聲明為static對局部數(shù)組聲明,使該數(shù)組不必在每次調(diào)用函數(shù)時(shí)生成和初始化,該數(shù)組在程序中每次退出函數(shù)時(shí)不會刪除,這樣可以調(diào)高性能。
c++使用模擬的按引用調(diào)用,自動(dòng)將數(shù)組傳遞給函數(shù),被調(diào)用函數(shù)可以修改調(diào)用者原數(shù)組中的元素值。但各個(gè)數(shù)組元素和簡單變量一樣還是按值傳遞。
有程序中的函數(shù)不能修改數(shù)組元素。這時(shí)候需要在數(shù)組前添加const,數(shù)組元素成為函數(shù)體中的常量。
第五章 指針與字符串
指針變量的值為內(nèi)存地址。
盡管不是必須的,但在指針變量名中加上ptr字樣能更清楚地表示這些變量是指針,需要相應(yīng)的處理。
作為一種風(fēng)格, 很多人不愿意在程序中到處出現(xiàn)未加修飾的0。因此定義了預(yù)處理宏NULL (在 和其它幾個(gè)頭文件中) 為空指針常數(shù), 通常是0 或者((void *)0) 。希望區(qū)別整數(shù)0 和空指針0 的人可以在需要空指針的地方使用NULL。使用NULL 只是一種風(fēng)格習(xí)慣; 預(yù)處理器把所有的NULL 都還原回0, 而編譯還是依照上文的描述處理指針上下文的0。特別是, 在函數(shù)調(diào)用的參數(shù)里, NULL之前(正如在0 之前) 的類型轉(zhuǎn)換還是需要。NULL 只能用作指針常數(shù);
&運(yùn)算符是一個(gè)一元運(yùn)算符,返回操作數(shù)的地址。
const限定符可以使程序猿告訴編譯器特定變量的值不能修改。
sizeof運(yùn)算符返回?cái)?shù)組中的總字節(jié)數(shù)為size_t類型的值,通常是unsigned int 類型。
數(shù)組取值的方法: *(bPtr + 3)即指針加偏移量。
數(shù)組名相當(dāng)于是數(shù)組中第一個(gè)元素的內(nèi)存地址。
c++中可以說字符串是個(gè)常量指針,是指向字符串中第一個(gè)字符的指針。從這個(gè)意義上說,字符串像數(shù)組一樣,因?yàn)閿?shù)組名也是第一個(gè)元素的指針。
char color[] = "blue"; char *colorPrt = "blue";
第一個(gè)聲明生成五個(gè)元素的數(shù)組color,包含字符'b','l','u','e'和'\0'。第二個(gè)聲明生成指針變量colorPtr,指向內(nèi)存中的字符串"blue"。有時(shí),可以將整行文本輸入數(shù)組中。為此,c++提供了cin.getline函數(shù)。cin.getline函數(shù)取三個(gè)參數(shù):存放該行文本的字符數(shù)組,長度和分隔符。
例如:
char semtence[80];
cin.getline(semtence,80,'\n');
聲明80個(gè)字符的數(shù)組,然后從鍵盤讀取一行文本到該數(shù)組中。函數(shù)遇到分隔符'\n',輸入文件結(jié)束符或讀取的字符數(shù)比第二個(gè)參數(shù)的長度少1時(shí)停止讀取字符。如果遇到分隔符,則讀取該分隔符并不再讀入下一個(gè)字符。cin.getline默認(rèn)第三個(gè)函數(shù)值為\n,因此函數(shù)可以寫成cin.getline(semtence,80);
第六章 類與數(shù)據(jù)抽象(一)
- 聲明一個(gè)結(jié)構(gòu)體
struct Time{
int hour;
int min;
int second;
}
Time timeObject,timeArray[10],*timePtr,&timeRef = timeObject;
聲明timeObject為Time類型變量,timeArray為10個(gè)Time類型元素的數(shù)組,timePtr為Time對象的指針,timeRef為Time對象的引用。
如果要打印hour成員:
cout << timeobject.hour;
cout << timeRef.hour;
timePtr = &timeObject;
cout << timePtr -> hour;
- 聲明一個(gè)類
class Time{
public:
Time();
void setTime (int, int, int)
void printMilitary();
void printStandard();
private:
int hour;
int minut;
int second;
};
- 聲明一個(gè)類方法
void Time::printMilitary()
{
cout << ( hour < 10 ? "0" : " ") << hour << ":"
<< ( minute < 10 ? "0" : " ") << minute;
}
實(shí)際對象只包含數(shù)據(jù),因此要比包含函數(shù)的對象小的多。對類名或該類的對象采用sizeof運(yùn)算符時(shí),只得到該類的數(shù)據(jù)長度。編譯器生成獨(dú)立于所有類對象的類成員函數(shù)副本(只有一份)。當(dāng)然,因?yàn)槊總€(gè)對象的數(shù)據(jù)是不同的,所以每個(gè)對象需要自己的類數(shù)據(jù)副本。該函數(shù)代碼是不變的,因此可以在一個(gè)類的所有對象之間共享。
}頭文件的#ifndef和 # define 預(yù)處理指令中用頭文件名,并將圓點(diǎn)換成下劃線。
#ifndef TIME1_H
#define TIME1_H
...
#defint
static局部對象的構(gòu)造函數(shù)只在程序執(zhí)行首次到達(dá)對象時(shí)調(diào)用一次,對應(yīng)的析構(gòu)函數(shù)在main終止或調(diào)用exit函數(shù)時(shí)調(diào)用。
析構(gòu)函數(shù)在函數(shù)名稱簽名加~
~Employee();
第七章 類與數(shù)據(jù)抽象(二)
const對象不能用賦值語句修改,因此應(yīng)初始化。類的數(shù)據(jù)成員聲明為const時(shí),要用成員初始化值向構(gòu)造函數(shù)提供類對象數(shù)據(jù)成員的初始值。
如果成員函數(shù)不修改對象,則將其聲明為const,這樣可以減少許多錯(cuò)誤。
void print() const;
- 符合increment(i) 將increment初始化為數(shù)值i。如果需要多個(gè)成員初始化值,則可以將其放在冒號后面以逗號分隔的列表中。所有數(shù)據(jù)成員都可以用成員初始化的語法進(jìn)行初始化,但const和引用必須用這種方式進(jìn)行初始化。
Increment::Increment(int c,int i)
: increment(i) //成員初始化語法
{ count = c ; } //賦值語句
increment被聲明為一個(gè)const值,如果不是用成員初始化語法,而使用賦值語句對其賦值,則會報(bào)錯(cuò):
{count = c;
increment = i;}
- 類可以將其他類對象作為自己的成員,這稱之為復(fù)合。
Employee::Employee(char *fname, char *lname, int bmonth, int bday, int byear, int hmonth, int hday, int hyear)
:birthDate (bmonth, bday, byear),
hireDate (hmonth, hday, hyear)
-
友元函數(shù)
友元關(guān)系是“給予”的,而不是“索取”的。
比較像oc中a函數(shù)需要b函數(shù)的熟悉,則在a函數(shù)中引用b函數(shù)。
點(diǎn)我-擴(kuò)展閱讀class Count{ friend void setX (Count &, int); public: ... private: ... void setX (count &c, int val){ c.x = val; } 每個(gè)對象都可以通過this指針訪問自己的地址。每個(gè)非static成員函數(shù)都能訪問所調(diào)用成員所在對象的this指針。
為了節(jié)約存儲空間,每個(gè)類的每個(gè)成員函數(shù)只有一個(gè)副本,該類的每個(gè)對象都可調(diào)用這個(gè)成員函數(shù)。另一方面每個(gè)對象又有自己的類數(shù)據(jù)成員副本。
this -> x 或者(*this).x
this指針的一個(gè)有趣用法是防止對象賦值給自己。
Time &setTime (int, int, int); 返回地址?
在ANSI C語言中,要為TypeName類型對象動(dòng)態(tài)分配內(nèi)存,可以用下列語句:
TypeName *typeNamePtr;
typeNamePtr = malloc(sizeof(typeName));
這就要求調(diào)用malloc函數(shù)和顯式使用sizeof運(yùn)算符,在ANSIC之前的c語言版本中,還要將malloc返回的指針進(jìn)行類型轉(zhuǎn)換(TypeName *)。malloc函數(shù)中沒有提供初始化所分配內(nèi)存塊的方法。
而在c++中,只要用下列語句:
typeNamePtr = new TypeName;
c++中允許對新生成的對象提供初始化值
float *thingPtr = new float (3.14159);
- static類變量表示的是類范圍中所有對象共享的信息。static數(shù)據(jù)成員的作用域是類范圍。
static的引入
static 是C++中很常用的修飾符,它被用來控制變量的存儲方式和可見性。函數(shù)內(nèi)部定義的變量,在程序執(zhí)行到它的定義處時(shí),編譯器為它在棧上分配空間,函數(shù)在棧上分配的空間在此函數(shù)執(zhí)行結(jié)束時(shí)會釋放掉,這樣就產(chǎn)生了一個(gè)問題:如果想將函數(shù)中此變量的值保存至下一次調(diào)用時(shí),如何實(shí)現(xiàn)? 最容易想到的方法是定義一個(gè)全局的變量,但定義為一個(gè)全局變量有許多缺點(diǎn),最明顯的缺點(diǎn)是破壞了此變量的訪問范圍(使得在此函數(shù)中定義的變量,不僅僅受此函數(shù)控制)。而static變量可以保持該變量的值,使得函數(shù)在下次調(diào)用時(shí)還保持上次函數(shù)退出時(shí)的值。static內(nèi)部機(jī)制
static被引入以告知編譯器,將變量存儲在程序的靜態(tài)存儲區(qū)而非棧上空間,靜態(tài)數(shù)據(jù)成員按定義出現(xiàn)的先后順序依次初始化,注意靜態(tài)成員嵌套時(shí),要保證所嵌套的成員已經(jīng)初始化了。static的優(yōu)勢:
可以節(jié)省內(nèi)存,因?yàn)樗撬袑ο笏械?,因此,對多個(gè)對象來說,靜態(tài)數(shù)據(jù)成員只存儲一處,供所有對象共用。靜態(tài)數(shù)據(jù)成員的值對每個(gè)對象都是一樣,但它的值是可以更新的。只要對靜態(tài)數(shù)據(jù)成員的值更新一次,保證所有對象存取更新后的相同的值,這樣可以提高時(shí)間效率。static類成員
類的對象構(gòu)建過程不會動(dòng)到static變量和函數(shù),因?yàn)樗嬖陟o態(tài)內(nèi)存,程序加載進(jìn)內(nèi)存的時(shí)候它就存在;而對象生命周期不同。static數(shù)據(jù)成員
static數(shù)據(jù)成員要在程序一開始運(yùn)行時(shí)就必須存在。因?yàn)楹瘮?shù)在程序運(yùn)行中被調(diào)用,所以靜態(tài)數(shù)據(jù)成員不能在任何函數(shù)內(nèi)分配空間和初始化。static數(shù)據(jù)成員要實(shí)際地分配空間,故不能在類的聲明中定義(只能聲明數(shù)據(jù)成員),也不能在頭文件中類聲明的外部定義,因?yàn)槟菚斐稍诙鄠€(gè)使用該類的源文件中,對其重復(fù)定義。static數(shù)據(jù)成員必須在類定義體的外部定義(正好一次)。不像普通數(shù)據(jù)成員,static成員不是通過類構(gòu)造函數(shù)進(jìn)行初始化,而是應(yīng)該在定義時(shí)進(jìn)行初始化。
在類中,靜態(tài)成員可以實(shí)現(xiàn)多個(gè)對象之間的數(shù)據(jù)共享,并且使用靜態(tài)數(shù)據(jù)成員還不會破壞隱藏的原則,即保證了安全性。因此,靜態(tài)成員是類的所有對象中共享的成員,而不是某個(gè)對象的成員。
靜態(tài)數(shù)據(jù)成員可以節(jié)省內(nèi)存,因?yàn)樗撬袑ο笏械?,因此,對多個(gè)對象來說,靜態(tài)數(shù)據(jù)成員只存儲一處,供所有對象共用。靜態(tài)數(shù)據(jù)成員的值對每個(gè)對象都是一樣,但它的值是可以更新的。只要對靜態(tài)數(shù)據(jù)成員的值更新一次,保證所有對象存取更新后的相同的值,這樣可以提高時(shí)間效率。
初始化格式為 <數(shù)據(jù)類型><類名>::<靜態(tài)數(shù)據(jù)成員名>=<值> 。初始化在類體外進(jìn)行,而前面不加static,以免與一般靜態(tài)變量或?qū)ο笙嗷煜?/p>
-
static成員函數(shù)
在靜態(tài)成員函數(shù)的實(shí)現(xiàn)中不能直接引用類中說明的非靜態(tài)成員,可以引用類中說明的靜態(tài)成員。如果靜態(tài)成員函數(shù)中要引用非靜態(tài)成員時(shí),可通過對象來引用。
靜態(tài)成員函數(shù),不屬于任何一個(gè)具體的對象,那么在類的具體對象聲明之前就已經(jīng)有了內(nèi)存區(qū),而非靜態(tài)數(shù)據(jù)成員還沒有分配內(nèi)存空間,那么在靜態(tài)成員函數(shù)中使用非靜態(tài)成員函數(shù),就好像沒有聲明一個(gè)變量卻提前使用它一樣。
static成員函數(shù)沒有this指針,不能被聲明為const,不能被聲明為虛函數(shù)。 類方法的調(diào)用
Employee::getCount();
即使在類沒有實(shí)例化任何對象時(shí),類的static數(shù)據(jù)成員和成員函數(shù)就已經(jīng)存在并可使用。將static成員函數(shù)聲明為const是個(gè)語法錯(cuò)誤。
刪除動(dòng)態(tài)分配內(nèi)存后,設(shè)置指向該內(nèi)存的指針指向0,這樣就切斷了指針與簽名所分配內(nèi)存的連接。
斷言: assert(first != 0 );
如果表達(dá)式值為false,則assert發(fā)出錯(cuò)誤消息,并調(diào)用abort函數(shù)終止程序執(zhí)行。這是個(gè)有用的調(diào)試工具,可測試變量是否有正確值。
第八章 運(yùn)算符重載
operator+ 重載運(yùn)算符+
運(yùn)算不重載不能改變運(yùn)算符用于內(nèi)部類型對象時(shí)的含義。運(yùn)算符重載只能喝用戶自定義類型的對象一起使用,或者用于用戶自定義類型的對象和內(nèi)部類型的對象混合使用。
未完待續(xù)
第九章 繼承
- 為了說明類CommissionWorker是從類Employee派生而來的,類CommissionWorker通常要做如下形式的定義:
class CommissionWorker : public Employee{
...
};
protected對于子、朋友來說,就是public的,可以自由使用,沒有任何限制,而對于其他的外部class,protected就變成private。
基類的public成員能夠被程序中所有函數(shù)訪問,private成員只能被基類的成員函數(shù)和友元訪問。
基類的protected成員只能被基類的成員和友元以及派生類的成員和友元訪問。
一般來說,聲明private類的數(shù)據(jù)成員和使用protected方式只能是系統(tǒng)要滿足特定性能要求時(shí)的“最后一招”。
把指向基類對象的指針顯式地強(qiáng)制轉(zhuǎn)換為派生類指針,然后引用該對象中并不存在的派生類的成員會導(dǎo)致運(yùn)行時(shí)的邏輯錯(cuò)誤。
在派生類中重定義基類成員
Employee::print();
派生類永遠(yuǎn)也不能直接訪問基類的private成員,但可通過基類pubic或protected成員間接訪問。
調(diào)用析構(gòu)函數(shù)的順序和調(diào)用構(gòu)造函數(shù)的順序相反。
用派生類指針引用基類的對象。這種引用方式會導(dǎo)致語法錯(cuò)誤。派生類指針必須先強(qiáng)制轉(zhuǎn)換為基類的指針。
??點(diǎn)語法和->的區(qū)別??
變量是對象的時(shí)候用“.”訪問
變量是對象指針的時(shí)候用“->”訪問
#inlclude <iostream>
using namespace std;
class A
{
public:
int x;
int y;
};
int main()
{
A a;
a.x=100; //對象用點(diǎn)訪問
// a->y=100; //error
A* pa = new A;
pa->y=200; //對象指針用箭頭
// pa.x=100; //error<br> delete pa;
return 0;
}
第十章 虛函數(shù)和多態(tài)性
- 虛函數(shù)的聲明
virtual void draw() const;
-
如果在基類中將函數(shù)draw聲明為virtual,然后用基類指針或引用指明派生類對象并使用該指針調(diào)用draw函數(shù)(shapePtr->draw()),則程序會
動(dòng)態(tài)的(即在運(yùn)行時(shí))選擇該派生類的draw函數(shù),這稱為動(dòng)態(tài)關(guān)聯(lián)。如果用點(diǎn)語法(squareObject.draw()),則被調(diào)用函數(shù)是在編譯時(shí)確定的(稱為靜態(tài)關(guān)聯(lián))。
派生類調(diào)用基類函數(shù)
HourlyWorker *hPtr = &h;
hPtr -> Employee::print();
C++封裝、繼承、多態(tài)擴(kuò)展閱讀
C++ 在繼承中虛函數(shù)、純虛函數(shù)、普通函數(shù),三者的區(qū)別
將基類的析構(gòu)函數(shù)聲明為虛析構(gòu)函數(shù)。基類析構(gòu)函數(shù)在派生類析構(gòu)函數(shù)之后自動(dòng)執(zhí)行。
如果一個(gè)類擁有虛函數(shù),即使該類不需要虛析構(gòu)函數(shù)也給它提供一個(gè)虛析構(gòu)函數(shù),這樣能夠使該類的派生類包含正確調(diào)用的析構(gòu)函數(shù)。
將構(gòu)造函數(shù)聲明為虛函數(shù)是語法錯(cuò)誤。構(gòu)造函數(shù)不能是虛函數(shù)。
虛函數(shù)(impure virtual)
C++的虛函數(shù)主要作用是“運(yùn)行時(shí)多態(tài)”,父類中提供虛函數(shù)的實(shí)現(xiàn),為子類提供默認(rèn)的函數(shù)實(shí)現(xiàn)。
子類可以重寫父類的虛函數(shù)實(shí)現(xiàn)子類的特殊化。
如下就是一個(gè)父類中的虛函數(shù):
class A{
public:
virtual void out2(string s) {
cout<<"A(out2):"<<s<<endl;
}
};
- 純虛函數(shù)(pure virtual)
C++中包含純虛函數(shù)的類,被稱為是“抽象類”。抽象類不能使用new出對象,只有實(shí)現(xiàn)了這個(gè)純虛函數(shù)的子類才能new出對象。
C++中的純虛函數(shù)更像是“只提供申明,沒有實(shí)現(xiàn)”,是對子類的約束,是“接口繼承”。
C++中的純虛函數(shù)也是一種“運(yùn)行時(shí)多態(tài)”。
如下面的類包含純虛函數(shù),就是“抽象類”:
class A{
public:
virtual void out1(string s)=0;
virtual void out2(string s) {
cout<<"A(out2):"<<s<<endl;
}
};
“函數(shù)printShapeName和print是虛函數(shù)(在基類被定義為純虛函數(shù))的實(shí)現(xiàn),如果不在類Point中重新定義這些函數(shù),那么Point仍然為抽象類則不能實(shí)例化Point對象”。
c++編譯有一個(gè)或幾個(gè)虛函數(shù)的類時(shí),對該類建立虛函數(shù)列表。列表讓執(zhí)行程序選擇每次執(zhí)行類的虛函數(shù)時(shí)正確的實(shí)現(xiàn)列表。
第十一章 C++輸入/輸出流
c++式的I/O是類型安全的。
c++的I/O是以字節(jié)流的形式實(shí)現(xiàn)的,流實(shí)際上就是一個(gè)字節(jié)序列。
cin:把整數(shù)變量grade的值從cin輸入到內(nèi)存中
cin >> grade;
cout
cerr: 到對象cerr的輸出是非緩沖輸出,也就是說會立即顯示出來。
clog:到對象clog的輸出是緩存輸出。即每次插入clog可能使其輸出保持在緩沖區(qū),要等待緩沖區(qū)刷新時(shí)才輸出。
cout << "C++\n"; 也可以用流操縱算子endl(行結(jié)束)實(shí)現(xiàn)轉(zhuǎn)義序列\(zhòng)n(換行符)的功能,也可以用flush刷新輸出緩沖區(qū):
cout << flush;
- 需要輸出指針變量的地址時(shí)可以使用void *類型。
char *string = "test";
cout << static_cast<void *>( string) << endl;
輸出結(jié)果:0x00416D50
- put:用于輸出一個(gè)字符。
cout.put(' A ');
cout.put(' A ').put(' \n ');
流讀取運(yùn)算符通常會跳過輸入流中的空格,tab鍵,換行符等等的空白字符,當(dāng)遇到輸入流中的文件結(jié)束符時(shí),流讀取運(yùn)算符返回0(false),否則,流讀取運(yùn)算符返回對調(diào)用該運(yùn)算符的對象的引用。當(dāng)輸入類型有錯(cuò)時(shí),流讀取運(yùn)算符就會設(shè)置輸入流的failbit狀態(tài)位,如果操作失敗則設(shè)置badbit狀態(tài)位。
cin.get() 其返回結(jié)果是所輸入的字符。當(dāng)遇到文件結(jié)尾符,返回0(該版本)。
cin.eof() 是否在cin中遇到文件結(jié)尾符。
cin:不讀入空格符,cin.get()要流入空格符。
C++中cin、cin.get()、cin.getline()、getline()、gets()等函數(shù)的用法
ignore 用于在需要時(shí)跳過流中指定數(shù)量的字符(默認(rèn)為1),或在遇到指定的分隔符(默認(rèn)分隔符是EOF)時(shí)結(jié)束。
putback 將最后一次用get從輸入流中提取的字符放回到輸入流中。
peek 返回輸入流中的下一個(gè)字符,但并不將其從輸入流中刪除。
調(diào)用成員函數(shù)read,write可實(shí)現(xiàn)無格式輸入/輸出。這兩個(gè)函數(shù)分別把一定量的字節(jié)寫入字符數(shù)組和從字符數(shù)組中輸出。這些字節(jié)都是未經(jīng)任何格式化的。
成員函數(shù)read把指定個(gè)數(shù)的字符輸入到字符數(shù)組中。
成員函數(shù)gcount統(tǒng)計(jì)最后輸入的字符個(gè)數(shù)。
int main() {
const int SIZE = 80;
char buffer [SIZE];
count << Enter a Senterce:\n";
cin.read( buffer, 20);
cout.writer( buffer, cin.gcount() );
cout << endl;
return 0 ;
}
dec 整數(shù)被解釋為十進(jìn)制。
oct 整數(shù)被解釋為八進(jìn)制。
hex 整數(shù)被解釋為十六進(jìn)制。
setbase();
setprecision或percision控制小數(shù)點(diǎn)后面的位數(shù)。該精度對之后所有的輸出操作都有效,直到下一次設(shè)置精度為止。
-
c++中,cout.width( )與setw( )有什么區(qū)別?
這兩個(gè)函數(shù)的作用是一樣的。都是控制輸出字符域?qū)挾鹊?,且不足用空格填充?br> 在C++中,setw(int n)用來控制輸出間隔。
例如:
cout<<'s'<<setw(8)<<'a'<<endl;
則在屏幕顯示
s a
//s與a之間有7個(gè)空格,setw()只對其后面緊跟的輸出產(chǎn)生作用,如上例中,表示'a'共占8個(gè)位置,不足的用空格填充。若輸入的內(nèi)容超過setw()設(shè)置的長度,則按實(shí)際長度輸出。
setw()默認(rèn)填充的內(nèi)容為空格,可以setfill()配合使用設(shè)置其他字符填充在c++中 以下函數(shù)可互用:
setw 或 width()
setfill 或 fill()
setprecision 或 precision()
其中前面的set* 需要加頭文件 #include<iomanip.h> 用戶自定義的流操縱蒜子
ostream& bell ( ostream& output ){
return output << ' \a';
}
flag是作者定義的int…一般是標(biāo)記的意思…做某種標(biāo)記…一般只等于0或1…輔助循環(huán)退出的…
setf( ) setiosflags( ) 設(shè)置輸出格式狀態(tài),括號中應(yīng)給出格式狀態(tài),內(nèi)容與控制符setiosflags括號中內(nèi)容相同.
ios::showpoint 強(qiáng)制輸出浮點(diǎn)數(shù)的小數(shù)點(diǎn)和尾數(shù)零。
ios::left,ios::right,ios::internal : left標(biāo)志可以使輸出域數(shù)據(jù)的右邊,right標(biāo)志可以使輸出域右對齊并把填充字符放在輸出數(shù)據(jù)的左邊。填充的字符由成員函數(shù)fill或參數(shù)化的流操縱蒜子setfill指定。
第十二章 模版
template< class T >
模版提供了軟件復(fù)用的好處。請記住,盡管模版只編寫一次,但程序中仍然實(shí)例化多個(gè)模版函數(shù)和模版類的副本。這些副本會占用大量內(nèi)存。(一個(gè)實(shí)現(xiàn)多個(gè)聲明)
- 模版與友元
第十三章 異常處理
- 傳統(tǒng)程序控制使用異常處理方法的另一危險(xiǎn)是堆棧解退,異常發(fā)生之前分配的資源可能無法釋放。這個(gè)問題可以通過認(rèn)真編程而避免。
未完待續(xù)...