1、第一個C++程序
一、文件擴展名
C++源代碼的文件擴展名.cpp、C、cxx、c(須要指定編譯語言)
自定義的頭文件依然保留.h
二、頭文件
C++標準庫的頭文件不帶.h,最經常使用的是iostream
C語言中的頭文件依然能夠繼續使用,stdio.h或cstdio
三、輸入輸出
cout<<輸出
cin>>輸入
endl換行
cout和cin再也不使用佔位符,它能夠自動識別數據類型。
scanf和printf能夠繼續使用。
四、編譯器
gcc也能夠編譯C++的源碼,但須要添加額外的參數
g++是編譯C++源碼的最簡單的編譯器,通常操做沒有默認安裝。
ubuntu系統的安裝指令:sudo apt-get install g++
以前的gcc的編譯參數,依然能夠繼續使用。
注意:C++編譯時的錯誤提示不是很精準,一個錯誤可能會產生大量的錯誤提示。
五、引入了名字空間概念
using namespace std;
2、C++中的基本數據類型
一、C++徹底兼容C語言中的全部數據類型(C++兼容C語言的全部語法。)。
二、添加了bool類型、字節寬度1,數值true(非零值),false(零值)。
三、在顯示bool變量前,使用boolalpha能夠以true或flase的形式顯示bool值。
四、void* 與其它類型指針的轉換受到限制
void* 不能夠直接給其它類型的指針賦值,必須通過強制轉換。
任意類型的指針均可以直接給void*賦值。
3、C++中的聯合、枚舉、結構
一、在C++中聯合、枚舉、結構設計成功後,再使用不須要加關鍵字。
二、枚舉的檢查更爲嚴格(C++中的枚舉是一種獨立的數據類型)。
三、結構成員中能夠有函數,在函數中能夠直接訪問結構的成員。
四、結構對象能夠繼續使用.或->訪問成員、成員函數。
五、結構中的成員添加了訪問屬性:
public:開放的,被它修飾過的成員在任何位置均可以訪問
private:私有的,被它修飾過的成員只能在成員函數中使用
protected:之後再說。
六、結構在建立時會自動調用一個函數-構造函數。
a、無返回值
b、名字與結構相同
c、參數能夠任意
七、結構在釋放時會自動調用一個函數-析構函數。
a、無返回值、參數
b、~結構名
練習:C++的走迷宮。
4、引用
一、引用就起"外號",爲一個標識符另外再取一個名字。
二、引用必需初始化,不然編譯錯誤。
三、引用不光能夠引用標識符,也能夠引用當即數(右值、字面值、常量),但必須加const屬性。
四、不能定義空引用,但"野引用"或"懸空引用"是存在的(引用了堆內存的數據,當堆內存釋放後就不該該再使用)。
五、引用只能是一次性的,沒法再更改(引用一旦成功後,它是個變量了這個身份至死不渝)。
六、引用能夠看成函數的參數,它引用的對象就是函數的實參,因此引用能夠達到指針的效果。
a、函數之間共享變量
b、提升參數的傳遞效率(比指針還要高)
c、能夠獲取參數
注意:能使用引用就不要再使用指針了。
引用可否徹底取代指針,不能夠。
七、引用也能夠看成函數的返回值,但毫不能返回局部變量的引用。
練習1:使用引用定義一個能夠交換兩人個變量值的函數。
練習2:定義一個函數,計算兩個整數的最大公約數和最小公倍數,最大公約數使用返回值返回,最小公倍數使用引用返回。
5、C++中的內存管理運算符
一、在C++中使用 new/delete 來管理內存,new用來申請內存,delete用來釋放內存。
二、new在內存時容許對內存進行初始化。
三、使用new建立結構對象時會自動調用構造函數,delete時會自動調用析構函數。
總結:malloc/free與new/delete的區別?
一、malloc/free標準庫的函數,使用時還須要添加頭文件,而new/delete是C++語言中的運算符。
二、malloc返回值的是void*指針,new返回的是有類型的指針。
三、malloc建立對象時不會調用構造函數,free時不會調用析構函數,但new/delete會自動調用構造和析構函數。
四、使用malloc使用內存時須要本身計算字節數,而使用new的時候會自動計算。
四、[]能夠配合new和delete申請或釋放數組。
new[]與不能夠與delete混用,必須使用delete[]釋放。
使用new[]/delete[]建立多少個對象就會調用屢次構造和析構。
五、new/delete與malloc/free不能混用。
六、delete不能夠重複釋放,但能夠釋放空指針。
七、若是使用new申請內存失敗會拋出異常"std::bad_alloc",異常的捕獲和處理會在之後講解。
6、C++中的函數
一、C++中函數能夠在main前執行,C語言中不能夠。
二、C++中的函數名能夠相同,只要參數不一樣便可(函數重載,不僅是參數)。
函數能夠同名並非真正意義上的同名,它只在編譯基本把函數的名字添加了額外信息(函數的參數),返回值不算內。
三、內聯函數
內聯函數就是把函數編譯成二進制,而後在須要的位置直接把函數拷貝過去,而不是跳轉後再執行,這樣能夠減小進棧、出棧、和調用,以此提升程序的執行效率,但這樣會增長可執行文件的大小。
內聯函數與宏函數的區別:從本質上來講它們是同樣的,但內聯函數能夠檢查參數,也能夠具備返回值。
inline 返回值 函數名(參數)
{
}
四、C++中函數的參數能夠有默認值
一、函數的默認參數要靠右。
二、默認參數要儘可能要少用,由於可能會引用重載錯誤。
三、默認參數是編譯器在編譯時幫助賦值的,因此只能由全局變量、靜態變量、字面值對參數進行賦值。
1、名字空間
C語言中的名字空間的劃分:全局、局部、塊
C++認爲:全局空間用起很是方便,但若是把太多的東西放在全局空間會形成命名衝突,因此C++引用了這樣一種機制就是名字空間。
名字空間:把全局的命名空間進一步分割,能夠建立出一個個獨立的命名空間防止相互之間衝突。
1、定義名字空間:
namespace name
{
變量;
函數;
結構、類;
}
2、名字空間的合併
a、同名的名字空間會自動合併。
b、在同一個名字空間中只標識符必須是惟一的。
3、定義與聲明分開
namespace n1
{
//在名字空間中聲明函數
void func(void);
}
// 在名字空間外定義函數
void n1::func(void)
{
}
4、如何使用名字空間中的內容
a、域限定符(::),直接使用,名字空間::標識符,這樣的好處是絕對不會衝突,但就是麻煩了些。
b、using namespace 名字空間; 功能是把名字空間中的標識符對以後的代碼所有公開。
c、using 名字空間::標識符,表示此標識符對後面的代碼公開。
5、名字空間的嵌套
名字空間能夠嵌套,但使用時要逐層解析。
namespace n1
{
int num = 10;
namespace n2
{
int num = 20;
namespace n3
{
int num = 30;
}
}
}
n1::n2::n3::num == 30;
n1::n2::num == 20;
n1::num = 10;
using namespace n1::n2;
六、全局空間歸屬爲匿名空間
在全局空間定義的標識符都屬於這個匿名空間,匿名空間默認開放。
若是函數中有同名的標識符把匿名空間中的屏蔽了,可使用空的域限定符表示它。
注意:不一樣命名空間中的同名函數不構成重載,同一做用域下的同名函數叫重載。
2、class
一、C++的class與struct同樣,是一種複合數據類型。
二、裏面能夠有變量用來表達屬性,函數用來表示行爲。
三、在C++的class與struct,幾乎沒有任何區別。
四、struct中默認訪問屬因而public,class中默認的訪問屬性是private。
五、在C++默認使用class,以示與C語言中的class進行區分。
練習:定義一個Date類: year,month,day,在類裏提供
一、年月日是否有效,返回bool類型
二、是不是閏年,返回bool類型
三、求nextday() ,返回下一天的日期
四、寫一個nextday(int n)表示n表後的日期,注意n可正可負
一、日期轉換整天數
二、由天數轉換成日期
3、class的構造函數
一、在建立對象時自動調用的函數,在整個對象的生命週期中必定會被調用一次,且只能被調用一次。
二、在構造函數中負責對成員變量的初始化、分配資源、設置對象的初始狀態。
三、構造函數能夠有多個版本,這些不一樣的版本之間會構造重載,建立對象時的方式不一樣、給的參數不一樣會調用相應的構造函數,若是調用的構造函數不存在可能會形成編譯錯誤。
// 無參構造
Student stu <=> Student* stup = new Student;
Student stu(參數列表) <=> Student* stup = new Student(參數列表);
四、若是類中沒有定義構造函數,編譯器會自動生成一個無參構造。
一旦定義了其它版本的構造函數,無參構造就不會再生成了,所以爲了防止無參方式建立對象出錯,在定構造函數時,至少要實現兩個。
五、無參構造未必無參,在C++中函數能夠有默認參數,若是有參構造所有設置了默認參數,就會和無參數構造有衝突,它們兩個只能有一個存在。
六、所謂的"編譯器生成的某某函數"
"編譯器生成的某某函數",不是真正意義上的函數,編譯做爲指令的生成者,只要生成具備某些函數功能的指令即,沒有必須生成高級語言的主義上的函數。
七、何時調用無參構造
a、Student stu <=> Student* stup = new Student;
b、建立對象數組,每一個對象都會調用一次無參構造。
c、若是類A中有成員是類B,當執行守類A的構造函數前會自動調用類B的無參構造。
d、在類A中如何調用類B的有參構造
類A(參數列表):成員類B(參數列表)
{
...
}
八、類型轉換構造函數
用一個數據給對象初始化,默認會自動調用構造函數,達到類型轉換的效果。
這種方式雖然使用方便,但也會包容一些錯誤存在,若是想讓代碼檢查更爲嚴格可使用explicit關鍵字禁止隱式轉換的方式調用構造函數。
九、也能夠實現自動類型轉換構造函數(默認)。
練習:
一、寫一個Date類,有屬性:年、月、日,實現其各類構造函數。
二、寫一個Timer類(屬性定義爲私有,方法定義爲公開)
有一個屬性 unsigned int second;//second記錄定時器的秒數
有一個屬性 Action action;//定時器響應動做
typedef bool (*Action)(void *);
有一個方法setAction(Action a),當調用begin()方法以後,second秒以後自動調用a函數。
三、使用class方式實現五子棋。