閱讀Android源碼須要對C++基礎語法有必定的認識,藉此對C++作一個簡單的語法認知。html
一、數據類型前端
類型 | 關鍵字 |
---|---|
布爾型 | bool |
字符型 | char |
整型 | int |
浮點型 | float |
雙浮點型 | double |
無類型 | void |
寬字符型 | wchar_t |
一些基本類型可使用一個或多個類型修飾符進行修飾:ios
(1)typedef 聲明編程
使用 typedef 爲一個已有的類型取一個新的名字。下面是使用 typedef 定義一個新類型的語法:typedef type newname;數組
(2)枚舉類型安全
枚舉類型(enumeration)是C++中的一種派生數據類型,它是由用戶定義的若干枚舉常量的集合。數據結構
若是一個變量只有幾種可能的值,能夠定義爲枚舉(enumeration)類型。所謂"枚舉"是指將變量的值一一列舉出來,變量的值只能在列舉出來的值的範圍內。編程語言
建立枚舉,須要使用關鍵字 enum。枚舉類型的通常形式爲:ide
enum 枚舉名{ 標識符[=整型常數], 標識符[=整型常數], ... 標識符[=整型常數] } 枚舉變量;
若是枚舉沒有初始化, 即省掉"=整型常數"時, 則從第一個標識符開始。函數
默認狀況下,第一個名稱的值爲 0,第二個名稱的值爲 1,第三個名稱的值爲 2,以此類推。可是,您也能夠給名稱賦予一個特殊的值,只須要添加一個初始值便可。例如,在下面的枚舉中,green 的值爲 5。
enum color { red, green=5, blue };
在這裏,blue 的值爲 6,由於默認狀況下,每一個名稱都會比它前面一個名稱大 1,但 red 的值依然爲 0。
(3)變量類型
變量的名稱能夠由字母、數字和下劃線字符組成。它必須以字母或下劃線開頭。
幾種基本變量類型:bool、char、int、float、double、void、wchar_t
C++ 也容許定義各類其餘類型的變量,好比枚舉、指針、數組、引用、數據結構、類等等。
例如,列出幾個有效的聲明:
int i, j, k; char c, ch; float f, salary; double d;
extern int d = 3, f = 5; // d 和 f 的聲明
int d = 3, f = 5; // 定義並初始化 d 和 f
byte z = 22; // 定義並初始化 z
char x = 'x'; // 變量 x 的值爲 'x'
(4)左值(Lvalues)和右值(Rvalues)
C++ 中有兩種類型的表達式:
變量是左值,所以能夠出如今賦值號的左邊。數值型的字面值是右值,所以不能被賦值,不能出如今賦值號的左邊。
(5)變量做用域
做用域是程序的一個區域,通常來講有三個地方能夠定義變量:
在函數或一個代碼塊內部聲明的變量,稱爲局部變量。
在函數參數的定義中聲明的變量,稱爲形式參數。
在全部函數外部聲明的變量,稱爲全局變量。
(6)常量
常量是固定值,在程序執行期間不會改變。這些固定的值,又叫作字面量。
常量能夠是任何的基本數據類型,可分爲整型數字、浮點數字、字符、字符串和布爾值。
整數常量能夠是十進制、八進制或十六進制的常量。
浮點常量由整數部分、小數點、小數部分和指數部分組成。可使用小數形式或者指數形式來表示浮點常量。
當使用小數形式表示時,必須包含整數部分、小數部分,或同時包含二者。當使用指數形式表示時, 必須包含小數點、指數,或同時包含二者。帶符號的指數是用 e 或 E 引入的。
例如:
3.14159 // 合法的 314159E-5L // 合法的 510E // 非法的:不完整的指數 210f // 非法的:沒有小數或指數 .e55 // 非法的:缺乏整數或分數
布爾常量共有兩個,它們都是標準的 C++ 關鍵字:
字符常量是括在單引號中。若是常量以 L(僅當大寫時)開頭,則表示它是一個寬字符常量(例如 L'x'),此時它必須存儲在 wchar_t 類型的變量中。不然,它就是一個窄字符常量(例如 'x'),此時它能夠存儲在 char 類型的簡單變量中。
字符常量能夠是一個普通的字符(例如 'x')、一個轉義序列(例如 '\t'),或一個通用的字符(例如 '\u02C0')。
在 C++ 中,有一些特定的字符(轉義序列碼),當它們前面有反斜槓時,它們就具備特殊的含義,被用來表示如換行符(\n)或製表符(\t)等。
字符串字面值或常量是括在雙引號 "" 中的。一個字符串包含相似於字符常量的字符:普通的字符、轉義序列和通用的字符。
定義常量:在 C++ 中,有兩種簡單的定義常量的方式:
(7)修飾符類型
C++ 容許在 char、int 和 double 數據類型前放置修飾符。修飾符用於改變基本類型的含義,因此它更能知足各類情境的需求。
下面列出了數據類型修飾符:
修飾符 signed、unsigned、long 和 short 可應用於整型,signed 和 unsigned 可應用於字符型,long 可應用於雙精度型。
修飾符 signed 和 unsigned 也能夠做爲 long 或 short 修飾符的前綴。例如:unsigned long int。
C++ 容許使用速記符號來聲明無符號短整數或無符號長整數。您能夠不寫 int,只寫單詞 unsigned、short 或 unsigned、long,int 是隱含的。例如:
unsigned x; unsigned int y;
(8)類型限定符
提供了變量的額外信息:
const | const 類型的對象在程序執行期間不能被修改改變。 |
volatile | 修飾符 volatile 告訴編譯器不須要優化volatile聲明的變量,讓程序能夠直接從內存中讀取變量。對於通常的變量編譯器會對變量進行優化,將內存中的變量值放在寄存器中以加快讀寫效率。 |
restrict | 由 restrict 修飾的指針是惟一一種訪問它所指向的對象的方式。只有 C99 增長了新的類型限定符 restrict。 |
(9)C++ 存儲類
存儲類定義 C++ 程序中變量/函數的範圍(可見性)和生命週期。這些說明符放置在它們所修飾的類型以前。下面列出 C++ 程序中可用的存儲類:
指示編譯器在程序的生命週期內保持局部變量的存在,而不須要在每次它進入和離開做用域時進行建立和銷燬。所以,使用 static 修飾局部變量能夠在函數調用之間保持局部變量的值。
static 修飾符也能夠應用於全局變量。當 static 修飾全局變量時,會使變量的做用域限制在聲明它的文件內。
用於提供一個全局變量的引用,全局變量對全部的程序文件都是可見的。當您使用 'extern' 時,對於沒法初始化的變量,會把變量名指向一個以前定義過的存儲位置。
當您有多個文件且定義了一個能夠在其餘文件中使用的全局變量或函數時,能夠在其餘文件中使用 extern 來獲得已定義的變量或函數的引用。能夠這麼理解,extern 是用來在另外一個文件中聲明一個全局變量或函數。
extern 修飾符一般用於當有兩個或多個文件共享相同的全局變量或函數的時候。
使用 thread_local 說明符聲明的變量僅可在它在其上建立的線程上訪問。 變量在建立線程時建立,並在銷燬線程時銷燬。 每一個線程都有其本身的變量副本。
thread_local 說明符能夠與 static 或 extern 合併。
能夠將 thread_local 僅應用於數據聲明和定義,thread_local 不能用於函數聲明或定義。例如:
thread_local int x; // 命名空間下的全局變量 class X { static thread_local std::string s; // 類的static成員變量 }; static thread_local std::string X::s; // X::s 是須要定義的 void foo() { thread_local std::vector<int> v; // 本地變量 }
(10)運算符
下類型的運算符:
運算符 | 描述 |
---|---|
sizeof | sizeof 運算符返回變量的大小。例如,sizeof(a) 將返回 4,其中 a 是整數。 |
Condition ? X : Y | 條件運算符。若是 Condition 爲真 ? 則值爲 X : 不然值爲 Y。 |
, | 逗號運算符會順序執行一系列運算。整個逗號表達式的值是以逗號分隔的列表中的最後一個表達式的值。 |
.(點)和 ->(箭頭) | 成員運算符用於引用類、結構和共用體的成員。 |
Cast | 強制轉換運算符把一種數據類型轉換爲另外一種數據類型。例如,int(2.2000) 將返回 2。 |
& | 指針運算符 & 返回變量的地址。例如 &a; 將給出變量的實際地址。 |
* | 指針運算符 * 指向一個變量。例如,*var; 將指向變量 var。 |
二、基本語法
(1)循環
循環類型 | 描述 |
---|---|
while 循環 | 當給定條件爲真時,重複語句或語句組。它會在執行循環主體以前測試條件。 |
for 循環 | 屢次執行一個語句序列,簡化管理循環變量的代碼。 |
do...while 循環 | 除了它是在循環主體結尾測試條件外,其餘與 while 語句相似。 |
嵌套循環 | 您能夠在 while、for 或 do..while 循環內使用一個或多個循環。 |
(2)判斷
語句 | 描述 |
---|---|
if 語句 | 一個 if 語句 由一個布爾表達式後跟一個或多個語句組成。 |
if...else 語句 | 一個 if 語句 後可跟一個可選的 else 語句,else 語句在布爾表達式爲假時執行。 |
嵌套 if 語句 | 您能夠在一個 if 或 else if 語句內使用另外一個 if 或 else if 語句。 |
switch 語句 | 一個 switch 語句容許測試一個變量等於多個值時的狀況。 |
嵌套 switch 語句 | 您能夠在一個 switch 語句內使用另外一個 switch 語句。 |
(3)函數
一個函數的組成部分:
若是函數要使用參數,則必須聲明接受參數值的變量。這些變量稱爲函數的形式參數。
形式參數就像函數內的其餘局部變量,在進入函數時被建立,退出函數時被銷燬。
當調用函數時,向函數傳遞參數的方式:
調用類型 | 描述 |
---|---|
傳值調用 | 該方法把參數的實際值複製給函數的形式參數。在這種狀況下,修改函數內的形式參數對實際參數沒有影響。 |
指針調用 | 該方法把參數的地址複製給形式參數。在函數內,該地址用於訪問調用中要用到的實際參數。這意味着,修改形式參數會影響實際參數。 |
引用調用 | 該方法把參數的引用複製給形式參數。在函數內,該引用用於訪問調用中要用到的實際參數。這意味着,修改形式參數會影響實際參數。 |
(4)數組
能夠存儲一個固定大小的相同類型元素的順序集合。數組是用來存儲一系列數據,但它每每被認爲是一系列相同類型的變量。
全部的數組都是由連續的內存位置組成。最低的地址對應第一個元素,最高的地址對應最後一個元素。
例如:double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
(5*)指針
每個變量都有一個內存位置,每個內存位置都定義了可以使用連字號(&)運算符訪問的地址,它表示了在內存中的一個地址。
指針是一個變量,其值爲另外一個變量的地址,即,內存位置的直接地址。就像其餘變量或常量同樣,您必須在使用指針存儲其餘變量地址以前,對其進行聲明。指針變量聲明的通常形式爲:
type *var-name;
(type 是指針的基類型,var-name 是指針變量的名稱。星號是用來指定一個變量是指針。)
例如:
int *ip; /* 一個整型的指針 */ double *dp; /* 一個 double 型的指針 */ float *fp; /* 一個浮點型的指針 */ char *ch; /* 一個字符型的指針 */
使用指針時會頻繁進行如下幾個操做:定義一個指針變量、把變量地址賦值給指針、訪問指針變量中可用地址的值。
例如:
#include <iostream> using namespace std; int main () { int var = 20; // 實際變量的聲明 int *ip; // 指針變量的聲明 ip = &var; // 在指針變量中存儲 var 的地址 cout << "Value of var variable: "; cout << var << endl; //20 // 輸出在指針變量中存儲的地址 cout << "Address stored in ip variable: "; cout << ip << endl; //地址 // 訪問指針中地址的值 cout << "Value of *ip variable: "; cout << *ip << endl; //20 return 0; }
(6)引用&
引用變量是一個別名,也就是說,它是某個已存在變量的另外一個名字。一旦把引用初始化爲某個變量,就可使用該引用名稱或變量名稱來指向變量。
例如:
int i = 17; int& r = i; //爲 i 聲明引用變量 double& s = d;
(7)結構
定義結構,必須使用 struct 語句。struct 語句定義了一個包含多個成員的新的數據類型。
例如:
#include <iostream> #include <cstring> using namespace std; // 聲明一個結構體類型 Books struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main( ) { Books Book1; // 定義結構體類型 Books 的變量 Book1 Books Book2; // 定義結構體類型 Books 的變量 Book2 // Book1 詳述 strcpy( Book1.title, "C++ 教程"); strcpy( Book1.author, "Runoob"); strcpy( Book1.subject, "編程語言"); Book1.book_id = 12345; // Book2 詳述 strcpy( Book2.title, "CSS 教程"); strcpy( Book2.author, "Runoob"); strcpy( Book2.subject, "前端技術"); Book2.book_id = 12346; // 輸出 Book1 信息 cout << "第一本書標題 : " << Book1.title <<endl; // 輸出 Book2 信息 cout << "第二本書標題 : " << Book2.title <<endl; return 0; }
能夠定義指向結構的指針,方式與定義指向其餘類型變量的指針類似,以下所示:
struct Books *struct_pointer;
如今,您能夠在上述定義的指針變量中存儲結構變量的地址。爲了查找結構變量的地址,請把 & 運算符放在結構名稱的前面,以下所示:
struct_pointer = &Book1;
爲了使用指向該結構的指針訪問結構的成員,您必須使用 -> 運算符,以下所示:
struct_pointer->title;
注:可使用typedf爲結構體定義別名
三、面向對象
(1)繼承
格式:
class derived-class: access-specifier base-class
其中,訪問修飾符 access-specifier 是 public、protected 或 private 其中的一個,base-class 是以前定義過的某個類的名稱。若是未使用訪問修飾符 access-specifier,則默認爲 private。
派生類能夠訪問基類中全部的非私有成員。所以基類成員若是不想被派生類的成員函數訪問,則應在基類中聲明爲 private。
一個派生類繼承了全部的基類方法,但下列狀況除外:
多繼承即一個子類能夠有多個父類,它繼承了多個父類的特性。
C++ 類能夠從多個類繼承成員,語法以下:
class <派生類名>:<繼承方式1><基類名1>,<繼承方式2><基類名2>,… { <派生類類體> };
(2)函數重載
在同一個做用域內,能夠聲明幾個功能相似的同名函數,可是這些同名函數的形式參數(指參數的個數、類型或者順序)必須不一樣。您不能僅經過返回類型的不一樣來重載函數。
(3)多態
當類之間存在層次結構,而且類之間是經過繼承關聯時,就會用到多態。
C++ 多態意味着調用成員函數時,會根據調用函數的對象的類型來執行不一樣的函數。
#include <iostream> using namespace std; class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } virtual int area() { cout << "Parent class area :" <<endl; return 0; } }; class Rectangle: public Shape{ public: Rectangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Rectangle class area :" <<endl; return (width * height); } }; class Triangle: public Shape{ public: Triangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Triangle class area :" <<endl; return (width * height / 2); } }; // 程序的主函數 int main( ) { Shape *shape; Rectangle rec(10,7); Triangle tri(10,5); // 存儲矩形的地址 shape = &rec; // 調用矩形的求面積函數 area shape->area(); // 存儲三角形的地址 shape = &tri; // 調用三角形的求面積函數 area shape->area(); return 0; }
虛函數 是在基類中使用關鍵字 virtual 聲明的函數。在派生類中從新定義基類中定義的虛函數時,會告訴編譯器不要靜態連接到該函數。
咱們想要的是在程序中任意點能夠根據所調用的對象類型來選擇調用的函數,這種操做被稱爲動態連接,或後期綁定。
想要在基類中定義虛函數,以便在派生類中從新定義該函數更好地適用於對象,可是在基類中又不能對虛函數給出有意義的實現,這個時候就會用到純虛函數。
例如:
class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } // pure virtual function virtual int area() = 0; };
= 0 告訴編譯器,函數沒有主體,上面的虛函數是純虛函數。
(4)數據抽象
只向外界提供關鍵信息,並隱藏其後臺的實現細節,即只表現必要的信息而不呈現細節。
(5)數據封裝
封裝是面向對象編程中的把數據和操做數據的函數綁定在一塊兒的一個概念,這樣能避免受到外界的干擾和誤用,從而確保了安全。數據封裝引伸出了另外一個重要的 OOP 概念,即數據隱藏。
數據封裝是一種把數據和操做數據的函數捆綁在一塊兒的機制,數據抽象是一種僅向用戶暴露接口而把具體的實現細節隱藏起來的機制。
C++ 經過建立類來支持封裝和數據隱藏(public、protected、private)。
例如:
class Box { public: double getVolume(void) { return length * breadth * height; } private: double length; // 長度 double breadth; // 寬度 double height; // 高度 };
(6)接口(抽象類)
接口描述了類的行爲和功能,而不須要完成類的特定實現。
C++ 接口是使用抽象類來實現的,抽象類與數據抽象互不混淆,數據抽象是一個把實現細節與相關的數據分離開的概念。
若是類中至少有一個函數被聲明爲純虛函數,則這個類就是抽象類。純虛函數是經過在聲明中使用 "= 0" 來指定的。
設計抽象類(一般稱爲 ABC)的目的,是爲了給其餘類提供一個能夠繼承的適當的基類。抽象類不能被用於實例化對象,它只能做爲接口使用。
所以,若是一個 ABC 的子類須要被實例化,則必須實現每一個虛函數,這也意味着 C++ 支持使用 ABC 聲明接口。若是沒有在派生類中重載純虛函數,就嘗試實例化該類的對象,會致使編譯錯誤。
可用於實例化對象的類被稱爲具體類。