久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

csdn(18條消息) 2021版C++教程,C++進階教程(最全C++教程)

 山峰云繞 2022-04-19

一,、C++教程前言介紹

https://blog.csdn.net/weixin_55305220/article/details/118668036?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_antiscanv2&utm_relevant_index=1

這部C++教程是大全教程,。其內(nèi)容涵蓋了C++語言的基本語法、面向?qū)ο?/a>的概念和程序設計方法,、數(shù)據(jù)結(jié)構(gòu)基礎(chǔ),、模板和泛型程序設計簡介。從零開始,、由淺入深,、層層遞進、細致而又詳盡地講解C++這門大型編程語言,。

可以關(guān)注 微 信 公 眾 號  “C和C加加”  回復 “ZXC” 即可獲取 詳細教程 和 PDF版,!

二、基本語法

  • 對象-對象具有狀態(tài)的行為,。對象是類的實例,。
  • 類-類可以定義為對象行為,、狀態(tài)的模版。
  • 方法-從基本上講,,一個方法表示一種行為,,一個類可以包含多種方法。
  • 變量


1,、注釋

2,、關(guān)鍵字

3、標識符

標識符是用來標識變量,、函數(shù),、類、模塊,,或任何其他用戶自定義項目的名稱,。一個標識符以字母 A-Z 或 a-z 或下劃線 _ 開始,后跟零個或多個字母,、下劃線和數(shù)字(0-9),。

標識符內(nèi)不允許出現(xiàn)標點字符,比如 @,、& 和 %,。C++ 是區(qū)分大小寫的編程語言。

三,、數(shù)據(jù)類型


1,、第一個C++程序

 2、基本數(shù)據(jù)類型

七種基本的C++數(shù)據(jù)類型:bool,、char,、int、float,、double,、void、wchar_t

類型修飾符:signed,、unsigned,、short、long

注:一些基本類型可以使用一個或多個類型修飾符進行修飾,,比如:signed short int簡寫為short,、signed long int 簡寫為long。

3,、數(shù)據(jù)類型在不同系統(tǒng)中所占空間大小

 這個與機器,、操作系統(tǒng)、編譯器有關(guān)。比如同樣是在32bits的操作系統(tǒng)系,,VC++的編譯器下int類型為占4個字節(jié),;而tuborC下則是2個字節(jié)。

原因:

c/c++規(guī)定int字長和機器字長相同

操作系統(tǒng)字長和機器字長未必一致

編譯器根據(jù)操作系統(tǒng)字長來定義int字長

4,、typedef聲明

5,、枚舉類型

C++中的一種派生數(shù)據(jù)類型,它是由用戶定義的若干枚舉常量的集合,;枚舉元素是一個整型,,枚舉型可以隱式的轉(zhuǎn)換為int型,int型不能隱式的轉(zhuǎn)換為枚舉型,。

如果枚舉沒有初始化, 即省掉"=整型常數(shù)"時, 則從第一個標識符開始;

默認情況下,,第一個名稱的值為 0,第二個名稱的值為 1,,第三個名稱的值為 2,,以此類推。但是,,您也可以給名稱賦予一個特殊的值,,只需要添加一個初始值即可。

例如:

6 ,、常量及符號

(1)整型常量

整型常量可以分為有符號整型常量和無符號整型常量

八進制:以0開頭,,即以0作為八進制數(shù)的前綴,每位取值范圍是0~7,,八進制數(shù)通常是無符號數(shù)。

例如:016,、0101,、0128都是合法的八進制數(shù)
十六進制:以0x或者0X開頭,其數(shù)碼取值范圍0 ~ 9,,以及A ~ F或者a ~ f

例如:0X2A1,、0XC5、0XFFFF都是合法的16進制數(shù)

(2)實型常量

小數(shù)表示法:由整數(shù)部分和小數(shù)部分組成,,整數(shù)部分和小數(shù)部分每位取值范圍是0~9,,例如:0.0、3.25,、0.00596,、2.0
指數(shù)表示法:指數(shù)部分以符號"e"或者"E"開始,但必須是整數(shù),,并且符號"e"或"E"兩邊都必須有一個數(shù),,例如:1.2e20和-3.4e-2

(3)字符常量

字符常量是單引號括起來的字符,例如:'a'和'?'都是合法字符常量。字符'a'的ASCII碼值是97,,字符'A'的ASCII碼值是41,,字符'?'的ASCII碼值是63

轉(zhuǎn)義字符是特殊的字符常量,使用時以字符串’'代表開始轉(zhuǎn)義,,和后面不同的字符表示轉(zhuǎn)義的字符,。轉(zhuǎn)義字符表如下所示:

 (4)字符串常量

是由一對雙引號括起來的零個或多個字符序列,例如:“welcome to our school”,、“hello world”,。""可以表示一個空字符串。

字符常量’A’和字符串常量"A"是不同的,,字符串常量"A"是由'A'和'\0'兩個字符組成的,,字符串長度是2,字符串常量'A'只是一個字符,,沒有長度,。

(5)其他常量

  • 布爾常量:布爾常量只有兩個,一個是true,,表示真,;另一個是false,表示假,。
  • 枚舉常量:枚舉型數(shù)據(jù)中定義的成員也是常量,,這將在后文介紹。
  • 宏定義常量:通過#define宏定義的一些值也是常量,。例如:define PI3.1415,。其中PI就是常量。

7,、變量

變量其實只不過是程序可操作的存儲區(qū)的名稱,。C++ 中每個變量都有指定的類型,類型決定了變量存儲的大小和布局,,該范圍內(nèi)的值都可以存儲在內(nèi)存中,,運算符可應用于變量上。

(1)標識符:是用來對C++程序中的常量,、變量,、語句標號以及用戶自定義函數(shù)的名稱進行標識的符號。
標識符命名規(guī)則:

  • 有字母,、數(shù)字及下劃線組成,,且不能以數(shù)字開頭。
  • 大寫和小寫字母代表不同意義,。
  • 不能與關(guān)鍵字同名
  • 盡量“見名知義”,,應該受一定規(guī)則的約束,。
  • 不合法的標識符:6A、ABC*,、case(保留字)

c++保留關(guān)鍵字,,如圖所示:

(2)變量與變量說明:變量使用前一定要定義或說明,變量聲明的一般形式如下:[修飾符] 類型 變量名標識符,;

類型是變量類型的說明符,,說明變量的數(shù)據(jù)類型。修改師傅是任選的,,可以沒有,。
在這里插入圖片描述

 (3)整型變量:整型變量可以分為短整型、整型和長整型,,變量類型說明符分別是short,、int、long,。根據(jù)是否有符號還可分為以下6種,。

  • 整型 [signed] int
  • 無符號整型 unsigned [int]
  • 有符號短整型 [signed] short [int]
  • 無符號短整型 unsigned short [int]
  • 有符號長整型 [signed] long [int]
  • 無符號長整型 unsigned long [int]

 (4)實型變量:又稱為浮點型變量,變量可分為單精度(float),、雙精度(double)和長雙精度(long double)三種,。

(5)變量賦值:變量值是動態(tài)改變的,每次改變都需要進行賦值運算,。變量賦值的形式如下:變量名標識符 = 表達式,,例如:

 (6)變量賦初值:可以在聲明變量的時候就把數(shù)據(jù)賦給變量,這個過程叫變量賦初值,,賦初值的情況有以下幾種:

  • int x=5;:表示定義x為有符號的基本整型變量,,賦初值為5
  • int x,y,,z=6;:表示定義x,、y、z為有符號的基本整型變量,,z賦初值為6
  • int x=3,y=3,,z=3;:表示定義x,、y、z為有符號的基本整型變量,,且賦予的初值均為3

(7)字符變量

  • 一個字符類型,,即可以字符形式輸出,也可以整數(shù)類型輸出:

  • 允許對字符數(shù)據(jù)進行算術(shù)運算,,此時就是對它們的ASCII碼值進行算術(shù)運算: 

(8)變量的作用域

局部變量:在函數(shù)或一個代碼塊內(nèi)部聲明的變量,,稱為局部變量。它們只能被函數(shù)內(nèi)部或者代碼塊內(nèi)部的語句使用。
全局變量:在所有函數(shù)外部定義的變量(通常是在程序的頭部),,稱為全局變量,。全局變量的值在程序的整個生命周期內(nèi)都是有效的。

局部變量和全局變量的名稱可以相同,,但是在函數(shù)內(nèi),,局部變量的值會覆蓋全局變量的值。
當局部變量被定義時,,系統(tǒng)不會對其初始化,;定義全局變量時,系統(tǒng)會自動初始化值:int float double 0,,char ’\0',,指針 NULL

8、自定義數(shù)據(jù)類型

(1)結(jié)構(gòu)體

結(jié)構(gòu)體可以包含不同數(shù)據(jù)類型的結(jié)構(gòu),。

定義結(jié)構(gòu)體的一般形式

結(jié)構(gòu)體變量名的定義和初始化:

  1. //定義結(jié)構(gòu)體同時聲明結(jié)構(gòu)體變量名
  2. struct 結(jié)構(gòu)體類型名
  3. {
  4. 成員類型1 成員名1;
  5. 成員類型2 成員名2;
  6. ... ...
  7. 成員類型n 成員名n;
  8. }變量名1,變量名2,...變量名n;
  9. //先定義結(jié)構(gòu)體
  10. [struct] 結(jié)構(gòu)體類型名 變量名;
  11. //直接定義
  12. struct
  13. {
  14. 成員類型1 成員名1;
  15. 成員類型2 成員名2;
  16. ... ...
  17. 成員類型n 成員名n;
  18. }變量名1,變量名2,...變量名n;
  19. struct person
  20. {
  21. int year;
  22. int age;
  23. string name;
  24. }p1 = {2019,24,"heiren"}, p1 = { 2020,24,"heiren" };
  25. struct person
  26. {
  27. int year;
  28. int age;
  29. string name;
  30. };
  31. struct person p1 = { 2019,24,"heiren" }, p1 = { 2020,24,"heiren" };
  32. struct
  33. {
  34. int year;
  35. int age;
  36. string name;
  37. }p1 = {2019,24,"heiren"}, p1 = { 2020,24,"heiren" };

結(jié)構(gòu)體變量的使用:

  • 具有相同類型的結(jié)構(gòu)體變量可以進行賦值運算,,但是不能輸入輸出
  • 對結(jié)構(gòu)體變量的成員引用:結(jié)構(gòu)體變量名.成員名
  • 指向結(jié)構(gòu)體的指針變量引用格式:指針變量名->成員名;
    結(jié)構(gòu)體數(shù)組的定義,初始化和使用與結(jié)構(gòu)體變量,、基本類型數(shù)組相似
  1. struct person
  2. {
  3. int year;
  4. int age;
  5. string name;
  6. }p[2] ={ {2019,24,"heiren"}, { 2020,24,"heiren" }};//可以不指定數(shù)組元素個數(shù)
  7. p[1].age;

結(jié)構(gòu)體作為函數(shù)傳遞有三種:值傳遞,,引用傳遞,指針傳遞

結(jié)構(gòu)體大小和字節(jié)對齊
    現(xiàn)代計算機中內(nèi)存空間都是按照byte劃分的,,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,,但實際情況是在訪問特定類型變量的時候經(jīng)常在特 定的內(nèi)存地址訪問,這就需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,,而不是順序的一個接一個的排放,,這就是對齊.
    為什么需要字節(jié)對齊?各個硬件平臺對存儲空間的處理上有很大的不同,。一些平臺對某些特定類型的數(shù)據(jù)只能從某些特定地址開始存取,。比如有些平臺每次讀都是從偶地址開始,如果一個int型(假設為32位系統(tǒng))如果存放在偶地址開始的地方,,那么一個讀周期就可以讀出這32bit,,而如果存放在奇地址開始的地方,就需要2個讀周期,,并對兩次讀出的結(jié)果的高低字節(jié)進行拼湊才能得到該32bit數(shù)據(jù),。
三個個概念:

自身對齊值:數(shù)據(jù)類型本身的對齊值,結(jié)構(gòu)體或類的的自身對齊值是其成員中最大的那個值,,例如char類型的自身對齊值是1,,short類型是2;
指定對齊值:編譯器或程序員指定的對齊值,,32位單片機的指定對齊值默認是4,;
有效對齊值:自身對齊值和指定對齊值中較小的那個,。
字節(jié)對齊的三個準則
結(jié)構(gòu)體變量的首地址能夠被其有效對齊值的大小所整除
結(jié)構(gòu)體的總大小為結(jié)構(gòu)體有效對齊值的整數(shù)倍。
結(jié)構(gòu)體每個成員相對于結(jié)構(gòu)體首地址的偏移量都是有效對齊值的整數(shù)倍,。
可以通過#pragma pack(n)來設定變量以n字節(jié)對齊方式

 (2)公用體(union)

幾個不同的變量共享同一個地址開始的內(nèi)存空間,。

成員類型可以是基本數(shù)據(jù)類型,也可以是構(gòu)造數(shù)據(jù)類型,。
公用體變量初始化時,,只能對第一個成員賦值。
公用體變量所占的內(nèi)存長度等于最長的成員長度,。
公用體變量在一個時刻只能一個成員發(fā)揮作用,,賦值時,成員之間會互相覆蓋,,最后一次被賦值的成員起作用,。
定義:

  1. union 共同體類型名
  2. {
  3. 成員類型1 成員名1;
  4. 成員類型2 成員名2;
  5. ... ...
  6. 成員類型n 成員名n;
  7. };

初始化

  1. union data
  2. {
  3. int i;
  4. float f;
  5. char c;
  6. }x = {123};
  7. union data
  8. {
  9. float f;
  10. int i;
  11. char c;
  12. };
  13. data x = {12.3};
  14. union
  15. {
  16. char c;
  17. int i;
  18. float f;
  19. }x = {’y'};

引用

  1. 共同體變量名.成員名;
  2. union data
  3. {
  4. int i;
  5. float f;
  6. char c;
  7. }x = {12};
  8. int main()
  9. {
  10. cout << x.i << " " << x.f << " " << x.c << endl;//12 1.68156e-44
  11. x.c = 'c';
  12. cout << x.i <<" "<< x.f << " " << x.c << endl;//99 1.38729e-43 c
  13. return 0;
  14. }

9、數(shù)據(jù)輸入與輸出

(1)控制臺屏幕

(2)操作控制

在頭文件iomanip.h中定義了一些控制流輸出格式的函數(shù),,默認情況下整型數(shù)按十進制形式輸出,,也可以通過hex將其設置為十六進制輸出。流操作的控制具體函數(shù)如下

 

 四,、運算符與表達式

1,、運算符

(1)算術(shù)運算符:算術(shù)運算主要指常用的加(+)、減(-),、乘(*),、除(/)四則運算,算術(shù)運算符中有單目運算符和雙目運算符,。

 

 

(2)關(guān)系運算符

關(guān)系運算符主要是對兩個對象進行比較,,運算結(jié)果是邏輯常量真或假。 

(3)邏輯運算符

邏輯運算符是對真和假這兩種邏輯值進行運算,,運算后的結(jié)果仍是一個邏輯值

 

(4)賦值運算符

(5)位運算符
在這里插入圖片描述

 

 (6)移位運算符

 

 

 (7)sizeof運算符

(8)條件運算符 

 

(9)逗號運算符 

 (10)運算符優(yōu)先級

(11) 運算符重載

所謂重載,,就是賦予新的含義。函數(shù)重載(Function Overloading)可以讓一個函數(shù)名有多種功能,,在不同情況下進行不同的操作,。運算符重載(Operator Overloading)也是一個道理,同一個運算符可以有不同的功能。

運算符重載是通過函數(shù)實現(xiàn)的,它本質(zhì)上是函數(shù)重載。
允許重載的運算符

不允許重載的運算符

重載運算符遵循的規(guī)則:

  • 不可以自己定義新的運算符,,只能對已有的C++運算符重載。
  • 不能改變運算符運算對象的個數(shù)。
  • 不能改變運算符的優(yōu)先級和結(jié)合性
  • 應與標準類型運算功能相似,避免影響可讀性。

一般格式:

  1. 函數(shù)類型 operator運算符(參數(shù)列表)
  2. {
  3. 函數(shù)體
  4. }
  5. //舉個栗子:定義一個向量類,通過運算符重載,可以用+進行運算。
  6. class Vector3
  7. {
  8. public:
  9. Vector3();
  10. Vector3(double x,double y,double z);
  11. public:
  12. Vector3 operator+(const Vector3 &A)const;
  13. void display()const;
  14. private:
  15. double m_x;
  16. double m_y;
  17. double m_z;
  18. };
  19. Vector3::Vector3() :m_x(0.0), m_y(0.0), m_z(0.0) {}
  20. Vector3::Vector3(double x, double y,double z) : m_x(x), m_y(y), m_z(z) {}
  21. //運算符重載
  22. Vector3 Vector3::operator+(const Vector3 &A) const
  23. {
  24. Vector3 B;
  25. B.m_x = this->m_x + A.m_x;
  26. B.m_y = this->m_y + A.m_y;
  27. B.m_z = this->m_z + A.m_z;
  28. return B;
  29. }
  30. void Vector3::display()const
  31. {
  32. cout<<"(" << m_x << "," << m_y << "," << m_z << ")" << endl;
  33. }

 運算符重載的形式有兩種:重載函數(shù)作為類的成員,,重載函數(shù)作為類的友元函數(shù)
根據(jù)運算符操作數(shù)的不同:雙目運算符作為類成員函數(shù),單目運算符作為類的成員函數(shù),,雙目運算符作為類的友員函數(shù),,單目運算符作為類的友元函數(shù),。

雙目運算符作為友元函數(shù)時需要制定兩個參數(shù),。
運算符重載函數(shù)作為類成員函數(shù)可以顯式調(diào)用。

常用運算符的重載

  • 自增自減
  • 賦值運算符
  • 輸入\輸出運算符重載

2,、表達式

(1)算數(shù)表達式

(2)關(guān)系表達式

(3)條件表達式 

(4)賦值表達式

(5)邏輯表達式 

(6) 逗號表達式

五,、語法結(jié)構(gòu)

1,、while循環(huán)

  1. while(conditon)//0為false,非0為true
  2. {
  3. statement(s);
  4. }

2、do…while循環(huán)

 3,、while與do…while比較

 

 4,、for

  1. for(init;conditon;increment)//0為false,非0或什么也不寫為true
  2. {
  3. statement(s);
  4. }
  • init首先被執(zhí),且只會執(zhí)行一次,,也可以不寫任何語句。
  • 然后會判斷conditon,true執(zhí)行循環(huán)主體,,false跳過循環(huán)
  • 執(zhí)行完循環(huán)主體,執(zhí)行increment,跳到2
  1. int array[5] = { 11, 22, 33, 44, 55 };
  2. for (int x : array)
  3. {
  4. cout << x << " ";
  5. }
  6. cout << endl;
  7. // auto 類型也是 C++11 新標準中的,,用來自動獲取變量的類型
  8. for (auto x : array)
  9. {
  10. cout << x << " ";
  11. }
  • for each
    STL中的for增強循環(huán)。
  1. int a[4] = { 4,3,2,1 };
  2. for each (int var in a)
  3. {
  4. cout << var << " ";
  5. }

5,、判斷結(jié)構(gòu)

  • if
  1. if(expr)
  2. {
  3. statement;//如果expr為true將執(zhí)行的語句塊
  4. }
  5. if(expr)
  6. {
  7. statement1;// 如果expr為true將執(zhí)行的語句塊
  8. }
  9. else
  10. {
  11. statement2;// 如果expr為false將執(zhí)行的語句
  12. }
  13. if(expr1)
  14. {
  15. statement1;// 如果expr1為true將執(zhí)行的語句塊
  16. }
  17. elseif(expr2)
  18. {
  19. statement2;// 如果expr2為true將執(zhí)行的語句塊
  20. }
  21. ...
  22. else
  23. {
  24. statementElse;// 當上面的表達式都為false執(zhí)行的語句塊
  25. }
  • switch
  1. switch(expression){
  2. case constant-expression :
  3. statement(s);
  4. break;
  5. case constant-expression :
  6. statement(s);
  7. break;
  8. // 您可以有任意數(shù)量的 case 語句
  9. default : // 可選的
  10. statement(s);
  11. }

每個case后滿的常量表達式必須各不相同,。
case語句和default語句出現(xiàn)的順序?qū)?zhí)行結(jié)果沒有影響。
若case后沒有break,執(zhí)行完就不會判斷,,繼續(xù)執(zhí)行下一個case語句,。直到遇到brerak。
default后面如果沒有case,,則break可以省略
多個case可以用一組執(zhí)行語句

  1. char c = 'A';
  2. switch (c)
  3. {
  4. case 'A':
  5. case 'B':
  6. case 'C':
  7. cout << "及格了" << endl;
  8. break;
  9. default:
  10. cout << "不及格" << endl;
  11. }

6,、循環(huán)控制

 

 

7、循環(huán)嵌套 

 

 8,、三元運算符

  1. //如果 Exp1 為真,,則計算 Exp2 的值,,結(jié)果即為整個 ? 表達式的值。如果 Exp1 為假,,則計算 Exp3 的值,,結(jié)果即為整個 ? 表達式的值
  2. Exp1 ? Exp2 : Exp3;

9、預處理命令

預處理程序(刪除程序注釋,,執(zhí)行預處理命令等)–>編譯器編譯源程序

  • 宏定義:#define 標識符 字符串
  • 文件包含:#include<filename> 或者#include“filename”
  • 條件編譯
  1. //如果標識符被#define定義過,,執(zhí)行程序段1,否則執(zhí)行程序段2
  2. #ifdef 標識符
  3. 程序段1
  4. #else
  5. 程序段2
  6. #endif
  7. //如果標識符沒有被#define定義過,,執(zhí)行程序段1,,否則執(zhí)行程序段2
  8. #ifndef 標識符
  9. 程序段1
  10. #else
  11. 程序段2
  12. #endif
  13. //如果表達式為true,執(zhí)行程序段1,,否則執(zhí)行程序段2
  14. #if 表達式
  15. 程序段1
  16. #else
  17. 程序段2
  18. #endif

六,、數(shù)組和指針

1、一維數(shù)組

 初始化的形式:數(shù)據(jù)類型 數(shù)組名[常量表達式] = {初值表};
為數(shù)組的某一個元素賦值:數(shù)組名[下標] =值(下標從0開始)
數(shù)組的引用:數(shù)組名[下標]

  • 初始化數(shù)組時,,可以只給部分數(shù)組元素賦值
  • 對全部元素數(shù)組賦值時,,可以不指定數(shù)組長度,編譯系統(tǒng)會根據(jù)初值個數(shù)確定數(shù)組的長度,。
  • static型數(shù)組元素不賦初值,系統(tǒng)會自動默認為0,。

2,、二維數(shù)組

定義一維數(shù)組的形式:數(shù)據(jù)類型 數(shù)據(jù)名[常量表達式1][常量表達式2]
初始化的形式:數(shù)據(jù)類型 數(shù)組名[常量表達式1] [常量表達式2]= {初值表};
為數(shù)組的某一個元素賦值:數(shù)組名[行下標][列下標] =值(下標從0開始)
數(shù)組的引用:數(shù)組名[行下標][列下標]

將所有數(shù)據(jù)寫在一個花括號內(nèi),自動按照數(shù)組元素個數(shù)在內(nèi)存中排列的順序賦值
可對部分元素賦值,,其余元素的值自動取0.
定義初始化數(shù)組時,,可以省略第一維的長度,第二維不能省,,系統(tǒng)會自動確認行數(shù)

3,、字符數(shù)組

char類型的數(shù)組,在字符數(shù)組中最后一位為’\0’)時,,可以看成時字符串,。在C++中定義了string類,在Visual C++中定義了Cstring類,。
字符串中每一個字符占用一個字節(jié),,再加上最后一個空字符。

4,、指針

指針是一個變量,,其值為另一個變量的地址。即內(nèi)存位置的直接地址,。
聲明的一般形式:

  • 數(shù)據(jù)類型是指針變量所指向的變量的數(shù)據(jù)類型,,*表示其后的變量為指針變量
  1. 數(shù)據(jù)類型 *指針變量名;
  2. int *ip; //整型的指針
  3. double *dp; //double 型的指針
  4. float *fp; //浮點型的指針
  5. char *ch; //字符型的指針

指針變量的初始化:

  • &是取地址運算符,,&變量名表示變量的地址。
  • 變量的數(shù)據(jù)類型必須于指針變量的數(shù)據(jù)類型一致,。
  • 為了安全起見,,有時會把指針初始化為空指針(NULL或0)
  1. 數(shù)據(jù)類型 *指針變量名 = &變量名;
  2. *指針變量名 = &變量名;
  3. int a;
  4. int *p = &a;
  5. int *p2;
  6. p2 = &a;

指針變量的引用:

  • & 取地址符 * 指針運算符(間接運算符),其后是指針變量,,表示該指針變量所指向的變量,。
  • & *的優(yōu)先級是相同的,結(jié)合方式都是自左向右,。比如 &*p等價于&(*p),。
  1. int x = 3;
  2. int y;
  3. int *p;
  4. p = &x;
  5. y = *p;//y = a

指針運算(地址運算)

算術(shù)運算(移動指針運算):加減,自增自減,。
p+n運算得到的地址是p+n*sizeof(數(shù)據(jù)類型),。
兩個相同數(shù)據(jù)類型的指針可以進行加減運算,一般用于數(shù)組的操作中,。
關(guān)系運算:指針指向同一串連續(xù)存儲單元才有意義,,比如數(shù)組。與0比較,,判斷是不是空指針,。
賦值運算:變量地址賦值給指針變量,數(shù)組元素地址賦值給指針變量,,指針變量賦值給其他指針變量,。

  1. int arr[10],len;
  2. int *p1 = &arr[2],*p2 = &arr[5];
  3. len = p2-p1;//arr[2] 和arr[5]之間的元素個數(shù) 3

new和delete運算符

  • new-為變量分配內(nèi)存空間;
  • 可以通過判斷new返回的指針的值,,判斷空間是否分配成功,。
  • delete-釋放空間
  1. 指針變量 = new 數(shù)據(jù)類型(初值);
  2. delete 指針變量;
  3. delete[] 指針變量;//釋放為多個變量分配的地址
  4. int *ip;
  5. ip= new int(1);
  6. delete ip;
  7. int *ip;
  8. ip= new int[10];
  9. for (int i = 0; i < 10;i++)
  10. {
  11. ip[i] = i;
  12. }
  13. delete[] ip;
  14. int a[3][4] = {0};

5、指針與數(shù)組

 

 

6,、數(shù)組與new(動態(tài)創(chuàng)建數(shù)組) 

一維數(shù)組

  1. int* arr1 = new int[2];//delete []arr1;
  2. int* arr2 = new int[3]{ 1,2 };//delete []arr2

二維數(shù)組

  1. int m=2, n=3;
  2. int** arr3 = new int*[2];//delete []arr3
  3. for (int i = 0; i < 10; ++i)
  4. {
  5. arr3[i] = new int[3]; // delete []arr3[i]
  6. }
  7. int* arr4 = new int[m*n];//數(shù)據(jù)按行存儲 delete []arr3

7,、指針與字符串

  • 字符串數(shù)組名:char ch[] = "heiren";char *p = ch;
  • 字符串:char *p = "heiren";
  • 指針賦值運算:char * p;p = "Heiren";
    指針與函數(shù),指針可以作為函數(shù)的參數(shù),,也可以作為函數(shù)的返回值,。

8、指向函數(shù)的指針

 

 9,、引用

引用可以看做是數(shù)據(jù)的一個別名,,通過這個別名和原來的名字都能夠找到這份數(shù)據(jù),類似于window中的快捷方式,。

引用不占內(nèi)存空間,,必須在定義的同時初始化,且不能再引用其他數(shù)據(jù),。
引用在定義時需要添加&,,在使用時不能添加&,,使用時添加&表示取地址
引用型變量聲明:數(shù)據(jù)類型 &引用名 = 變量名;

  1. int a;
  2. int &b = a;//a和b表示相同的變量,具有相同的地址,。

引用可以作為函數(shù)參數(shù),,也可以作為函數(shù)返回值。

  1. void swap(int &r1, int &r2) {
  2. int temp = r1;
  3. r1 = r2;
  4. r2 = temp;
  5. }
  6. int &add1(int &r) {
  7. r += 1;
  8. return r;
  9. }
  10. int main()
  11. {
  12. int a = 12;
  13. int b = add1(a);
  14. cout << a << " "<<b << endl;//13 13
  15. return 0;
  16. }

將引用作為函數(shù)返回值時不能返回局部數(shù)據(jù)的引用,,因為當函數(shù)調(diào)用完成后局部數(shù)據(jù)就會被銷毀,。
函數(shù)在棧上運行,函數(shù)掉用完,,后面的函數(shù)調(diào)用會覆蓋之前函數(shù)的局部數(shù)據(jù),。

  1. int &add1(int &r) {
  2. r += 1;
  3. int res = r;
  4. return res;
  5. }
  6. void test()
  7. {
  8. int xx = 123;
  9. int yy = 66;
  10. }
  11. int main()
  12. {
  13. int a = 12;
  14. int &b = add1(a);
  15. int &c = add1(a);
  16. test();//函數(shù)調(diào)用,覆蓋之前函數(shù)的局部數(shù)據(jù)
  17. cout << a << " "<<b <<" "<< c<<endl;//14 -858993460 -858993460
  18. return 0;
  19. }

七,、函數(shù)

1,、函數(shù)聲明與定義

  • 函數(shù)類型-函數(shù)的返回值類型;函數(shù)名-必須符合C++標識符命名規(guī)則,,后面必須跟一對括號,;函數(shù)體-實現(xiàn)函數(shù)功能的主題部分;參數(shù)列表-函數(shù)名后面的括號內(nèi),,用于向函數(shù)傳遞數(shù)值或帶回數(shù)值,。
  • 函數(shù)聲明中,參數(shù)名可以省略,,參數(shù)類型和函數(shù)的類型不能省略,。
  • 函數(shù)聲明可以放在主調(diào)函數(shù)內(nèi)部,放在調(diào)用語句之前,;也可以放在主調(diào)函數(shù)外,如果位于所有定義函數(shù)之前,,后面函數(shù)定義順序任意,,各個主調(diào)函數(shù)調(diào)用也不必再做聲明
  • 當函數(shù)定義在前,函數(shù)調(diào)用災后,,可以不用函數(shù)聲明,。

后兩條總結(jié)一下就是:調(diào)用函數(shù)前,程序得知道有這個函數(shù),,聲明就是提前讓程序知道有這么的玩意

函數(shù)聲明:

  1. 函數(shù)類型 函數(shù)名(參數(shù)列表);
  2. eg:
  3. int max(int a,int b);//聲明函數(shù)時,,a,b可以省略
  4. int max(int,int);
  5. void show();

函數(shù)定義:

  1. 函數(shù)類型 函數(shù)名(參數(shù)列表)
  2. {
  3. 函數(shù)體;
  4. }
  5. eg:
  6. int max(int a,int b)
  7. {
  8. int z;
  9. z = a>b?a:b;
  10. return z;
  11. }

2、函數(shù)參數(shù)以及返回值

  • 形參:函數(shù)定義后面括號里的參數(shù),,函數(shù)調(diào)用前不占內(nèi)存,。
  • 實參:函數(shù)調(diào)用括號里的參數(shù),可以是常量,,變量或表達式等,。

形參和實參必須個數(shù)相同,、類型一致,順序一致,,函數(shù)傳遞方式:傳值,,指針,引用

 

 

 

 3,、函數(shù)調(diào)用

  • 函數(shù)可以單獨作為一個語句使用,。有返回值的函數(shù),可將函數(shù)調(diào)用作為語句的一部分,,利用返回值參與運算,。
    函數(shù)調(diào)用形式:參數(shù)傳遞–>函數(shù)體執(zhí)行–>返回主調(diào)函數(shù)
  1. 函數(shù)名(實參列表);
  2. show();

 函數(shù)的嵌套調(diào)用:

  1. int a()
  2. {
  3. return 666;
  4. }
  5. int b(int sum)
  6. {
  7. return sum+a()
  8. }
  9. int main()
  10. {
  11. cout<<b(222)<<endl;//888
  12. return 0;
  13. }

 函數(shù)的遞歸調(diào)用:直接遞歸調(diào)用和間接遞歸調(diào)用

  • 一個函數(shù)直接或間接遞歸調(diào)用該函數(shù)本身,稱為函數(shù)的遞歸調(diào)用
  • 遞歸和回歸:原問題=>子問題 子問題的解=>原問題的解
  1. //直接遞歸調(diào)用:求1+...n的值
  2. int total(int sum)
  3. {
  4. if (sum == 1)
  5. {
  6. return 1;
  7. }
  8. return sum + total(sum - 1);
  9. }
  10. int main()
  11. {
  12. cout << "total = " << total(10) << endl;//total = 55
  13. system("pause");
  14. return 0;
  15. }
  16. //間接遞歸調(diào)用
  17. int f2();
  18. int f1()
  19. {
  20. ...
  21. f2()
  22. }
  23. int f2()
  24. {
  25. f1();
  26. }

4,、重載函數(shù)

5,、內(nèi)聯(lián)函數(shù)

八、字符串(string)

1,、字符串的定義和初始化

  1. //定義
  2. string 變量;
  3. string str1;
  4. //賦值
  5. string str2 = "ShangHai";
  6. string str3 = str2;
  7. str3[3] = '2';//對某個字符賦值
  8. //字符串數(shù)組
  9. string 數(shù)組名[常量表達式]
  10. string arr[3];

2,、字符串的處理函數(shù)

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <string>
  4. string str;//生成空字符串
  5. string s(str);//生成字符串為str的復制品
  6. string s(str, strbegin,strlen);//將字符串str中從下標strbegin開始、長度為strlen的部分作為字符串初值
  7. string s(cstr, char_len);//以C_string類型cstr的前char_len個字符串作為字符串s的初值
  8. string s(num ,c);//生成num個c字符的字符串
  9. string s(str, stridx);//將字符串str中從下標stridx開始到字符串結(jié)束的位置作為字符串初值
  10. size()和length();//返回string對象的字符個數(shù)
  11. max_size();//返回string對象最多包含的字符數(shù),,超出會拋出length_error異常
  12. capacity();//重新分配內(nèi)存之前,,string對象能包含的最大字符數(shù)
  13. >,>=,<,<=,==,!=//支持string與C-string的比較(如 str<”hello”)。 使用>,>=,<,<=這些操作符的時候是根據(jù)“當前字符特性”將字符按字典順序進行逐一得 比較,,string (“aaaa”) <string(aaaaa),。
  14. compare();//支持多參數(shù)處理,支持用索引值和長度定位子串來進行比較,。返回一個整數(shù)來表示比較結(jié)果,,返回值意義如下:0:相等 1:大于 -1:
  15. push_back()
  16. insert( size_type index, size_type count, CharT ch );//在index位置插入count個字符ch
  17. insert( size_type index, const CharT* s );//index位置插入一個常量字符串
  18. insert( size_type index, const CharT* s, size_type n);//index位置插入常量字符串
  19. insert( size_type index, const basic_string& str );//index位置插入常量string中的n個字符
  20. insert( size_type index, const basic_string& str, size_type index_str, size_type n);//index位置插入常量str的從index_str開始的n個字符
  21. insert( size_type index, const basic_string& str,size_type index_str, size_type count = npos);//index位置插入常量str從index_str開始的count個字符,count可以表示的最大值為npos.這個函數(shù)不構(gòu)成重載 npos表示一個常數(shù),,表示size_t的最大值,,string的find函數(shù)如果未找到指定字符,返回的就是一個npos
  22. iterator insert( iterator pos, CharT ch );
  23. iterator insert( const_iterator pos, CharT ch );
  24. void insert( iterator pos, size_type n, CharT ch );//迭代器指向的pos位置插入n個字符ch
  25. iterator insert( const_iterator pos, size_type count, CharT ch );//迭代器指向的pos位置插入count個字符ch
  26. void insert( iterator pos, InputIt first, InputIt last );
  27. iterator insert( const_iterator pos, InputIt first, InputIt last );
  28. append() 和 + 操作符
  29. //訪問string每個字符串
  30. string s1("yuanrui"); // 調(diào)用一次構(gòu)造函數(shù)
  31. // 方法一: 下標法
  32. for( int i = 0; i < s1.size() ; i++ )
  33. cout<<s1[i];
  34. // 方法二:正向迭代器
  35. for( string::iterator iter = s1.begin();; iter < s1.end() ; iter++)
  36. cout<<*iter;
  37. // 方法三:反向迭代器
  38. for(string::reverse_iterator riter = s1.rbegin(); ; riter < s1.rend() ; riter++)
  39. cout<<*riter;
  40. iterator erase(iterator p);//刪除字符串中p所指的字符
  41. iterator erase(iterator first, iterator last);//刪除字符串中迭代器區(qū)間[first,last)上所有字符
  42. string& erase(size_t pos = 0, size_t len = npos);//刪除字符串中從索引位置pos開始的len個字符
  43. void clear();//刪除字符串中所有字符
  44. string& replace(size_t pos, size_t n, const char *s);//將當前字符串從pos索引開始的n個字符,,替換成字符串s
  45. string& replace(size_t pos, size_t n, size_t n1, char c); //將當前字符串從pos索引開始的n個字符,,替換成n1個字符c
  46. string& replace(iterator i1, iterator i2, const char* s);//將當前字符串[i1,i2)區(qū)間中的字符串替換為字符串s
  47. //tolower()和toupper()函數(shù) 或者 STL中的transform算法
  48. string s = "ABCDEFG";
  49. for( int i = 0; i < s.size(); i++ )
  50. s[i] = tolower(s[i]);
  51. transform(s.begin(),s.end(),s.begin(),::tolower);
  52. size_t find (constchar* s, size_t pos = 0) const;//在當前字符串的pos索引位置開始,查找子串s,,返回找到的位置索引,,-1表示查找不到子串
  53. size_t find (charc, size_t pos = 0) const;//在當前字符串的pos索引位置開始,查找字符c,,返回找到的位置索引,,-1表示查找不到字符
  54. size_t rfind (constchar* s, size_t pos = npos) const;//在當前字符串的pos索引位置開始,反向查找子串s,,返回找到的位置索引,,-1表示查找不到子串
  55. size_t rfind (charc, size_t pos = npos) const;//在當前字符串的pos索引位置開始,,反向查找字符c,返回找到的位置索引,,-1表示查找不到字符
  56. size_tfind_first_of (const char* s, size_t pos = 0) const;//在當前字符串的pos索引位置開始,,查找子串s的字符,返回找到的位置索引,,-1表示查找不到字符
  57. size_tfind_first_not_of (const char* s, size_t pos = 0) const;//在當前字符串的pos索引位置開始,,查找第一個不位于子串s的字符,返回找到的位置索引,,-1表示查找不到字符
  58. size_t find_last_of(const char* s, size_t pos = npos) const;//在當前字符串的pos索引位置開始,,查找最后一個位于子串s的字符,返回找到的位置索引,,-1表示查找不到字符
  59. size_tfind_last_not_of (const char* s, size_t pos = npos) const;//在當前字符串的pos索引位置開始,,查找最后一個不位于子串s的字符,返回找到的位置索引,,-1表示查找不到子串
  60. sort(s.begin(),s.end());
  61. substr(pos,n);//返回字符串從下標pos開始n個字符
  62. strtok()
  63. char str[] = "I,am,a,student; hello world!";
  64. const char *split = ",; !";
  65. char *p2 = strtok(str,split);
  66. while( p2 != NULL )
  67. {
  68. cout<<p2<<endl;
  69. p2 = strtok(NULL,split);
  70. }

九,、面向?qū)ο蠛皖?/strong>

面向?qū)ο蟾攀?/p>

1、類

類也是一種數(shù)據(jù)類型,。

類的聲明:

  1. class 類名
  2. {
  3. public:
  4. 公有數(shù)據(jù)成員;
  5. 公有成員函數(shù);
  6. private:
  7. 私有數(shù)據(jù)成員;
  8. 私有成員函數(shù);
  9. protected:
  10. 保護數(shù)據(jù)成員;
  11. 保護成員函數(shù);
  12. };

 成員函數(shù)的定義:類內(nèi),,類外,類外內(nèi)聯(lián)函數(shù)

  1. //類外
  2. 返回類型 類名:成員函數(shù)名(參數(shù)列表)
  3. {
  4. 函數(shù)體;
  5. }
  6. //內(nèi)聯(lián)函數(shù):類外
  7. inline 返回類型 類名:成員函數(shù)名(參數(shù)列表)
  8. {
  9. 函數(shù)體;
  10. }

2,、類成員的訪問權(quán)限以及類的封裝

C++中public,、private、protected只能修飾類的成員,,不能修飾類,,C++中的類沒有共有私有之分
類內(nèi)部沒有訪問權(quán)限的限制,都可以互相訪問,。
在C++中用class定義的類中,,其成員的默認存取權(quán)限是private。

3,、對象 

  1. //1.聲明類同時定義對象
  2. class 類名
  3. {
  4. 類體;
  5. }對象名列表;
  6. //2.先聲明類,再定義對象
  7. 類名 對象名(參數(shù)列表);//參數(shù)列表為空時,,()可以不寫
  8. //3. 不出現(xiàn)類名,,直接定義對象
  9. class
  10. {
  11. 類體;
  12. }對象名列表;
  13. //4.在堆上創(chuàng)建對象
  14. Person p(123, "yar");//在棧上創(chuàng)建對象
  15. Person *pp = new Person(234,"yar");//在堆上創(chuàng)建對象

注:不可以在定義類的同時對其數(shù)據(jù)成員進行初始化,因為類不是一個實體,,不合法但是能編譯運行
對象成員的引用:對象名.數(shù)據(jù)成員名 或者 對象名.成員函數(shù)名(參數(shù)列表)

4,、構(gòu)造函數(shù)

 構(gòu)造函數(shù)名必須與類名相同

沒有任何返回值和返回類型

創(chuàng)建對象自動調(diào)用,不需要用戶來調(diào)用,,且只掉用一次

類沒有定義任何構(gòu)造函數(shù),,編譯系統(tǒng)會自動為這個類生成一個默認的無參構(gòu)造函數(shù)
構(gòu)造函數(shù)定義

  1. //1.類中定義 2.類中聲明,,類外定義
  2. [類名::]構(gòu)造函數(shù)名(參數(shù)列表)
  3. {
  4. 函數(shù)體
  5. }

創(chuàng)建對象

類名 對象名(參數(shù)列表);//參數(shù)列表為空時,()可以不寫

帶默認參數(shù)的構(gòu)造函數(shù)

  1. class Person
  2. {
  3. public:
  4. Person(int = 0,string = "張三");
  5. void show();
  6. private:
  7. int age;
  8. string name;
  9. };
  10. Person::Person(int a, string s)
  11. {
  12. cout<<a<<" "<<s<<endl;
  13. age = a;
  14. name = s;
  15. }
  16. void Person::show()
  17. {
  18. cout << "age="<<age << endl;
  19. cout << "name=" <<name << endl;
  20. }
  21. int main()
  22. {
  23. Person p; //0 張三
  24. Person p2(12);//12 張三
  25. Person p3(123, "yar");//123 yar
  26. return 0;
  27. }

帶參數(shù)初始化表的構(gòu)造函數(shù)

  1. 類名::構(gòu)造函數(shù)名(參數(shù)列表):參數(shù)初始化表
  2. {
  3. 函數(shù)體;
  4. }
  5. 參數(shù)初始化列表的一般形式:
  6. 參數(shù)名1(初值1),參數(shù)名2(初值2),...,參數(shù)名n(初值n)
  7. class Person
  8. {
  9. public:
  10. Person(int = 0,string = "張三");
  11. void show();
  12. private:
  13. int age;
  14. string name;
  15. };
  16. Person::Person(int a, string s):age(a),name(s)
  17. {
  18. cout << a << " " << s << endl;
  19. }

構(gòu)造函數(shù)重載:構(gòu)造函數(shù)名字相同,,參數(shù)個數(shù)和參數(shù)類型不一樣,。

 拷貝構(gòu)造函數(shù)

  1. 類名::類名(類名&對象名)
  2. {
  3. 函數(shù)體;
  4. }
  5. class Person
  6. {
  7. public:
  8. Person(Person &p);//聲明拷貝構(gòu)造函數(shù)
  9. Person(int = 0,string = "張三");
  10. void show();
  11. private:
  12. int age;
  13. string name;
  14. };
  15. Person::Person(Person &p)//定義拷貝構(gòu)造函數(shù)
  16. {
  17. cout << "拷貝構(gòu)造函數(shù)" << endl;
  18. age = 0;
  19. name = "ABC";
  20. }
  21. Person::Person(int a, string s):age(a),name(s)
  22. {
  23. cout << a << " " << s << endl;
  24. }
  25. int main()
  26. {
  27. Person p(123, "yar");
  28. Person p2(p);
  29. p2.show();
  30. return 0;
  31. }
  32. //輸出
  33. 123 yar
  34. 拷貝構(gòu)造函數(shù)
  35. age=0
  36. name=ABC

5、析構(gòu)函數(shù)

 6,、對象指針

對象指針的聲明和使用

  1. 類名 *對象指針名;
  2. 對象指針 = &對象名;
  3. //訪問對象成員
  4. 對象指針->數(shù)據(jù)成員名
  5. 對象指針->成員函數(shù)名(參數(shù)列表)
  6. Person p(123, "yar");
  7. Person* pp = &p;
  8. Person* pp2 = new Person(234,"yar")
  9. pp->show();

 指向?qū)ο蟪蓡T的指針

  1. 數(shù)據(jù)成員類型 *指針變量名 = &對象名.數(shù)據(jù)成員名;
  2. 函數(shù)類型 (類名::*指針變量名)(參數(shù)列表);
  3. 指針變量名=&類名::成員函數(shù)名;
  4. (對象名.*指針變量名)(參數(shù)列表);
  5. Person p(123, "yar");
  6. void(Person::*pfun)();
  7. pfun = &Person::show;
  8. (p.*pfun)();

this指針
每個成員函數(shù)都有一個特殊的指針this,,它始終指向當前被調(diào)用的成員函數(shù)操作的對象

  1. class Person
  2. {
  3. public:
  4. Person(int = 0,string = "張三");
  5. void show();
  6. private:
  7. int age;
  8. string name;
  9. };
  10. Person::Person(int a, string s):age(a),name(s)
  11. {
  12. cout << a << " " << s << endl;
  13. }
  14. void Person::show()
  15. {
  16. cout << "age="<<this->age << endl;
  17. cout << "name=" <<this->name << endl;
  18. }

7、靜態(tài)成員

以關(guān)鍵字static開頭的成員為靜態(tài)成員,,多個類共享,。

  • static 成員變量屬于類,不屬于某個具體的對象
  • 靜態(tài)成員函數(shù)只能訪問類中靜態(tài)數(shù)據(jù)成員
    靜態(tài)數(shù)據(jù)成員
  1. //類內(nèi)聲明,,類外定義
  2. class xxx
  3. {
  4. static 數(shù)據(jù)類型 靜態(tài)數(shù)據(jù)成員名;
  5. }
  6. 數(shù)據(jù)類型 類名::靜態(tài)數(shù)據(jù)成員名=初值
  7. //訪問
  8. 類名::靜態(tài)數(shù)據(jù)成員名;
  9. 對象名.靜態(tài)數(shù)據(jù)成員名;
  10. 對象指針名->靜態(tài)數(shù)據(jù)成員名;

靜態(tài)成員函數(shù)

 8,、友元

借助友元(friend),可以使得其他類中得成員函數(shù)以及全局范圍內(nèi)得函數(shù)訪問當前類得private成員,。
友元函數(shù)

友元函數(shù)不是類的成員函數(shù),,所以沒有this指針,必須通過參數(shù)傳遞對象,。
友元函數(shù)中不能直接引用對象成員的名字,,只能通過形參傳遞進來的對象或?qū)ο笾羔榿硪迷搶ο蟮某蓡T。

  1. //1.將非成員函數(shù)聲明為友元函數(shù)
  2. class Person
  3. {
  4. public:
  5. Person(int = 0,string = "張三");
  6. friend void show(Person *pper);//將show聲明為友元函數(shù)
  7. private:
  8. int age;
  9. string name;
  10. };
  11. Person::Person(int a, string s):age(a),name(s)
  12. {
  13. cout << a << " " << s << endl;
  14. }
  15. void show(Person *pper)
  16. {
  17. cout << "age="<< pper->age << endl;
  18. cout << "name=" << pper->name << endl;
  19. }
  20. int main()
  21. {;
  22. Person *pp = new Person(234,"yar");
  23. show(pp);
  24. system("pause");
  25. return 0;
  26. }
  27. //2.將其他類的成員函數(shù)聲明為友元函數(shù)
  28. //person中的成員函數(shù)可以訪問MobilePhone中的私有成員變量
  29. class MobilePhone;//提前聲明
  30. //聲明Person類
  31. class Person
  32. {
  33. public:
  34. Person(int = 0,string = "張三");
  35. void show(MobilePhone *mp);
  36. private:
  37. int age;
  38. string name;
  39. };
  40. //聲明MobilePhone類
  41. class MobilePhone
  42. {
  43. public:
  44. MobilePhone();
  45. friend void Person::show(MobilePhone *mp);
  46. private:
  47. int year;
  48. int memory;
  49. string name;
  50. };
  51. MobilePhone::MobilePhone()
  52. {
  53. year = 1;
  54. memory = 4;
  55. name = "iphone 6s";
  56. }
  57. Person::Person(int a, string s):age(a),name(s)
  58. {
  59. cout << a << " " << s << endl;
  60. }
  61. void Person::show(MobilePhone *mp)
  62. {
  63. cout << mp->year << "年 " << mp->memory << "G " << mp->name << endl;
  64. }
  65. int main()
  66. {
  67. Person *pp = new Person(234,"yar");
  68. MobilePhone *mp = new MobilePhone;
  69. pp->show(mp);
  70. system("pause");
  71. return 0;
  72. }

友元類
當一個類為另一個類的友元時,,稱這個類為友元類,。 友元類的所有成員函數(shù)都是另一個類中的友元成員
語法形式:friend [class] 友元類名

  • 類之間的友元關(guān)系不能傳遞
  • 類之間的友元關(guān)系是單向的
  • 友元關(guān)系不能被繼承

十,、繼承和派生

1,、繼承

繼承就是再一個已有類的基礎(chǔ)上建立一個新類,已有的類稱基類或父類,,新建立的類稱為派生類和子類,;派生和繼承是一個概念,角度不同而已,,繼承是兒子繼承父親的產(chǎn)業(yè),,派生是父親把產(chǎn)業(yè)傳承給兒子。

一個基類可以派生出多個派生類,,一個派生類可以繼承多個基類

派生類的聲明:

 繼承方式:

public-基類的public成員和protected成員的訪問屬性保持不變,,私有成員不可見。
private-基類的public成員和protected成員成為private成員,只能被派生類的成員函數(shù)直接訪問,,私有成員不可見,。
protected-基類的public成員和protected成員成為protected成員,只能被派生類的成員函數(shù)直接訪問,私有成員不可見。

利用using關(guān)鍵字可以改變基類成員再派生類中的訪問權(quán)限,;using只能修改基類中public和protected成員的訪問權(quán)限,。

  1. class Base
  2. {
  3. public:
  4. void show();
  5. protected:
  6. int aa;
  7. double dd;
  8. };
  9. void Base::show(){
  10. }
  11. class Person:public Base
  12. {
  13. public:
  14. using Base::aa;//將基類的protected成員變成public
  15. using Base::dd;//將基類的protected成員變成public
  16. private:
  17. using Base::show;//將基類的public成員變成private
  18. string name;
  19. };
  20. int main()
  21. {
  22. Person *p = new Person();
  23. p->aa = 12;
  24. p->dd = 12.3;
  25. p->show();//出錯
  26. delete p;
  27. return 0;
  28. }

 派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)

  • 先執(zhí)行基類的構(gòu)造函數(shù),隨后執(zhí)行派生類的構(gòu)造函數(shù)
  • 先執(zhí)行派生類的析構(gòu)函數(shù),,再執(zhí)行基類的析構(gòu)函數(shù),。
  • 派生類的構(gòu)造函數(shù):派生類名(總參數(shù)列表):基類名(基類參數(shù)列表),子對象名1(參數(shù)列表){構(gòu)造函數(shù)體;}
  1. class Base
  2. {
  3. public:
  4. Base(int, double);
  5. ~Base();
  6. private:
  7. int aa;
  8. double dd;
  9. };
  10. Base::Base(int a, double d) :aa(a), dd(d)
  11. {
  12. cout << "Base Class 構(gòu)造函數(shù)!!!" << endl;
  13. }
  14. Base::~Base()
  15. {
  16. cout << "Base Class 析構(gòu)函數(shù)!!!" << endl;
  17. }
  18. class Person:public Base
  19. {
  20. public:
  21. Person(int,double,string);
  22. ~Person();
  23. private:
  24. string name;
  25. };
  26. Person::Person(int a,double d,string str):Base(a,d),name(str)
  27. {
  28. cout << "Person Class 構(gòu)造函數(shù)!!!" << endl;
  29. }
  30. Person::~Person()
  31. {
  32. cout << "Person Class 析構(gòu)函數(shù)!!!" << endl;
  33. }
  34. int main()
  35. {
  36. cout << "創(chuàng)建Person對象..." << endl;
  37. Person *p = new Person(1,2,"yar");
  38. cout << "刪除Person對象...." << endl;
  39. delete p;
  40. system("pause");
  41. return 0;
  42. }

2、多繼承

一個派生類同時繼承多個基類的行為,。

多繼承容易讓代碼邏輯復雜,、思路混亂,一直備受爭議,,中小型項目中較少使用,,后來的 Java、C#,、PHP 等干脆取消了多繼承,。

多重繼承派生類聲明的一般形式:

多重繼承派生類的構(gòu)造函數(shù):

 二義性問題:多個基類中有同名成員,出現(xiàn)訪問不唯一的問題,。

  • 1.類名::同名成員名;
  • 2.派生類定義同名成員,,訪問的就是派生類同名成員。

3,、虛基類

c++引入虛基類使得派生類再繼承間接共同基類時只保留一份同名成員,。

虛繼承的目的是讓某個類做出聲明,承諾愿意共享它的基類,。其中,,這個被共享的基類就稱為虛基類(Virtual Base Class)。
派生類的 同名成員 比虛基類的 優(yōu)先級更高
虛基類的聲明:class 派生類名:virtual 繼承方式 基類名

  1. class A//虛基類
  2. {
  3. protected:
  4. int a;
  5. };
  6. class B: virtual public A
  7. {
  8. protected:
  9. int b;
  10. };
  11. class C:virtual public A
  12. {
  13. protected:
  14. int c;
  15. };
  16. class D:public B,public C
  17. {
  18. protected:
  19. int d;
  20. void show()
  21. {
  22. b = 123;
  23. c = 23;
  24. a = 1;
  25. }
  26. };

 如果 B 或 C 其中的一個類定義了a,,也不會有二義性,,派生類的a 比虛基類的a 優(yōu)先級更高。

如果 B 和 C 中都定義了 a,,那么D直接訪問a 將產(chǎn)生二義性問題,。
應用:c++中的iostream , istream ,, ostream,,base_io

4、向上轉(zhuǎn)型

數(shù)據(jù)類型的轉(zhuǎn)換,,編譯器會將小數(shù)部分直接丟掉(不是四舍五入)

 只能將將派生類賦值給基類(C++中稱為向上轉(zhuǎn)型): 派生類對象賦值給基類對象,、將派生類指針賦值給基類指針、將派生類引用賦值給基類引用
派生類對象賦值給基類對象,,舍棄派生類新增的成員,;派生類指針賦值給基類指針,,沒有拷貝對象的成員,,也沒有修改對象本身的數(shù)據(jù),,僅僅是改變了指針的指向;派生類引用賦值給基類引用,,和指針的一樣,。、
上轉(zhuǎn)型后通過基類的對象,、指針,、引用只能訪問從基類繼承過去的成員(包括成員變量和成員函數(shù)),不能訪問派生類新增的成員

5,、多態(tài)

 不同的對象可以使用同一個函數(shù)名調(diào)用不同內(nèi)容的函數(shù),。

  • 靜態(tài)多態(tài)性-在程序編譯時系統(tǒng)就決定調(diào)用哪個函數(shù),比如函數(shù)重載和靜態(tài)多態(tài)性
  • 動態(tài)多態(tài)性-在程序運行過程中動態(tài)確定調(diào)用那個函數(shù),,通過虛函數(shù)實現(xiàn)的,。

6、虛函數(shù)

在基類中不執(zhí)行具體的操作,,只為派生類提供統(tǒng)一結(jié)構(gòu)的虛函數(shù),,將其聲明為虛函數(shù)。

 實現(xiàn)程序多態(tài)性的一個重要手段,,使用基類對象指針訪問派生類對象的同名函數(shù),。

  • 將基類中的函數(shù)聲明為虛函數(shù),派生類中的同名函數(shù)自動為虛函數(shù),。
  • 聲明形式:virtual 函數(shù)類型 函數(shù)名 (參數(shù)列表);
  • 構(gòu)造函數(shù)不能聲明為虛函數(shù),,析構(gòu)函數(shù)可以聲明為虛函數(shù)。
  1. class A
  2. {
  3. public:
  4. virtual void show()
  5. {
  6. cout << "A show" << endl;
  7. }
  8. };
  9. class B: public A
  10. {
  11. public:
  12. void show()
  13. {
  14. cout << "B show" << endl;
  15. }
  16. };
  17. int main()
  18. {
  19. B b;
  20. b.show();//B show
  21. A *pA = &b;
  22. pA->show();//B show 如果show方法前沒用virtual聲明為虛函數(shù),,這里會輸出A show
  23. system("pause");
  24. return 0;
  25. }

7,、純虛函數(shù)

8、抽象類 

 十一,、IO流

 1,、流類和對象

輸入流-從輸入設備流向內(nèi)存的流。
輸出流-從內(nèi)存流出設備的流,。
內(nèi)存緩沖區(qū)-用來存放流中的數(shù)據(jù),。
輸入輸出流程:鍵盤輸入=》鍵盤緩沖區(qū)=(回車觸發(fā))》程序的輸入緩沖區(qū)=》'>>’提取數(shù)據(jù)
                        輸出緩沖區(qū)=(緩沖滿或endl)》'<<’送到 顯示器顯示
輸入/輸出流類:
iostream:ios ,istream,ostream,iostream
fstream:ifstream,ofstream,fstream
strstream:istrstream,ostrstream,strstream

  • istream 是用于輸入的流類,cin 就是該類的對象,。
  • ostream 是用于輸出的流類,,cout 就是該類的對象。
  • ifstream 是用于從文件讀取數(shù)據(jù)的類,。
  • ofstream 是用于向文件寫入數(shù)據(jù)的類,。
  • iostream 是既能用于輸入,又能用于輸出的類。
  • fstream 是既能從文件讀取數(shù)據(jù),,又能向文件寫入數(shù)據(jù)的類,。
  • istrstream 輸入字符串類
  • ostrstream 輸出字符串類
  • strstream 輸入輸出字符串流類

 2、標準輸入輸出流

C++的輸入/輸出流庫(iostream)中定義了4個標準流對象:cin(標準輸入流-鍵盤),,cout(標準輸出流-屏幕),,cerr(標準錯誤流-屏幕),clog(標準錯誤流-屏幕)

cerr 不使用緩沖區(qū),,直接向顯示器輸出信息,;而輸出到 clog 中的信息會先被存放到緩沖區(qū),緩沖區(qū)滿或者刷新時才輸出到屏幕,。
cout 是 ostream 類的對象,,ostream 類的無參構(gòu)造函數(shù)和復制構(gòu)造函數(shù)都是私有的,所以無法定義 ostream 類的對象,。
使用>>提取數(shù)據(jù)時,,系統(tǒng)會跳過空格,制表符,,換行符等空白字符,。所以一組變量輸入值時,可用這些隔開,。
輸入字符串,,也是跳過空白字符,會在串尾加上字符串結(jié)束標志\0,。

  1. int x;
  2. double y;
  3. cin>>x>>y;
  4. //輸入 22 66.0 兩個數(shù)之間可以用空格,、制表符和回車分隔數(shù)據(jù)
  5. char str[10];
  6. cin>>str;//hei ren 字符串中只有hei\0

輸入流中的成員函數(shù)

  • get函數(shù):cin.get(),cin.get(ch)(成功返回非0值,,否則返回0),,cin.get(字符數(shù)組(或字符指針),字符個數(shù)n,終止字符)

  •  getline函數(shù):cin.getline(字符數(shù)組(或字符指針),字符個數(shù)n,終止標志字符)讀取字符知道終止字符或者讀取n-1個字符,,賦值給指定字符數(shù)組(或字符指針)

  • cin.peek() 不會跳過輸入流中的空格,、回車符。在輸入流已經(jīng)結(jié)束的情況下,,cin.peek() 返回 EOF,。
  • ignore(int n =1, int delim = EOF)

  •  putback(char c),可以將一個字符插入輸入流的最前面,。

 輸出流對象

  • 插入endl-輸出所有數(shù)據(jù),,插入換行符,清空緩沖區(qū)
  • \n-輸出換行,,不清空緩沖區(qū)
  • cout.put(參數(shù)) 輸出單個字符(可以時字符也可以是ASII碼)

格式化輸出
iomanip 中定義的流操作算子:

  • *不是算子的一部分,,星號表示在沒有使用任何算子的情況下,,就等效于使用了該算子,例如,,在默認情況下,,整數(shù)是用十進制形式輸出的,等效于使用了 dec 算子

 流操作算子使用方法:cout << hex << 12 << "," << 24;//c,18

setiosflags() 算子
setiosflags() 算子實際上是一個庫函數(shù),,它以一些標志作為參數(shù),這些標志可以是在 iostream 頭文件中定義的以下幾種取值,,它們的含義和同名算子一樣,。

 多個標志可以用|運算符連接,表示同時設置,。例如:

 如果兩個相互矛盾的標志同時被設置,結(jié)果可能就是兩個標志都不起作用,應該用 resetiosflags 清除原先的標志

 ostream 類中的成員函數(shù):

 setf 和 unsetf 函數(shù)用到的flag,,與 setiosflags 和 resetiosflags 用到的完全相同。

十二,、文件操作 

文件-指存儲在外部介質(zhì)上的數(shù)據(jù)集合,,文件按照數(shù)據(jù)的組織形式不一樣,分為兩種:ASCII文件(文本/字符),,二進制文件(內(nèi)部格式/字節(jié))

ASCII文件輸出還是二進制文件,,數(shù)據(jù)形式一樣,對于數(shù)值數(shù)據(jù),,輸出不同

1,、文件類和對象

C++ 標準類庫中有三個類可以用于文件操作,它們統(tǒng)稱為文件流類,。這三個類是:

ifstream:輸入流類,,用于從文件中讀取數(shù)據(jù)。
ofstream:輸出流類,,用于向文件中寫人數(shù)據(jù),。
fstream:輸入/輸出流類,既可用于從文件中讀取數(shù)據(jù),,又可用于 向文件中寫人數(shù)據(jù),。
文件流對象定義:

 2、打開文件

 open函數(shù):void open(const char* szFileName, int mode);

ios::binary 可以和其他模式標記組合使用

流類的構(gòu)造函數(shù)
eg:ifstream::ifstream (const char* szFileName, int mode = ios::in, int); 

 3,、文件的讀寫

 

 

4,、文件指針移動操作

  • ifstream 類和 fstream 類有 seekg 成員函數(shù),可以設置文件讀指針的位置,;
  • ofstream 類和 fstream 類有 seekp 成員函數(shù),,可以設置文件寫指針的位置。
  • ifstream 類和 fstream 類還有 tellg 成員函數(shù),,能夠返回文件讀指針的位置,;
  • ofstream 類和 fstream 類還有 tellp 成員函數(shù),,能夠返回文件寫指針的位置。

函數(shù)原型

  1. ostream & seekp (int offset, int mode);
  2. istream & seekg (int offset, int mode);
  3. //mode有三種:ios::beg-開頭往后offset(>=0)字節(jié) ios::cur-當前往前(<=0)/后(>=0)offset字節(jié) ios::end-末尾往前(<=0)offect字節(jié)
  4. int tellg();
  5. int tellp();
  6. //seekg 函數(shù)將文件讀指針定位到文件尾部,,再用 tellg 函數(shù)獲取文件讀指針的位置,,此位置即為文件長度

 5、文本文件和二進制文件打開方式的區(qū)別

UNIX/Linux 平臺中,,用文本方式或二進制方式打開文件沒有任何區(qū)別,。
在 UNIX/Linux 平臺中,文本文件以\n(ASCII 碼為 0x0a)作為換行符號,;而在 Windows 平臺中,,文本文件以連在一起的\r\n(\r的 ASCII 碼是 0x0d)作為換行符號。
在 Windows 平臺中,,如果以文本方式打開文件,,當讀取文件時,系統(tǒng)會將文件中所有的\r\n轉(zhuǎn)換成一個字符\n,,如果文件中有連續(xù)的兩個字節(jié)是 0x0d0a,,則系統(tǒng)會丟棄前面的 0x0d 這個字節(jié),只讀入 0x0a,。當寫入文件時,,系統(tǒng)會將\n轉(zhuǎn)換成\r\n寫入。
用二進制方式打開文件總是最保險的,。

十三,、泛型和模板

  • 泛型程序設計在實現(xiàn)時不指定具體要操作的數(shù)據(jù)的類型的程序設計方法的一種算法,指的是算法只要實現(xiàn)一遍,,就能適用于多種數(shù)據(jù)類型,,優(yōu)勢在于代碼復用,減少重復代碼的編寫,。
  • 模板是泛型的基礎(chǔ),,是創(chuàng)建泛型類或函數(shù)的藍圖或公式

 1、函數(shù)模板

函數(shù)模板的一般形式:

  1. template<class T>或template<typename T>
  2. 函數(shù)類型 函數(shù)名(參數(shù)列表)
  3. {
  4. 函數(shù)體;
  5. }
  6. template<class T1,class T2,...>//class可以換成typename
  7. 函數(shù)類型 函數(shù)名(參數(shù)列表)
  8. {
  9. 函數(shù)體;
  10. }
  11. //舉個栗子
  12. template<class T> T max(T a, T b)
  13. {
  14. return a > b ? a : b;
  15. }
  16. int main()
  17. {
  18. cout <<"max value is "<< max(12,34) << endl;//34
  19. cout << "max value is " << max(12.4, 13.6) << endl;//13.6
  20. cout << "max value is " << max(12.4, 13) << endl;//error 沒有與參數(shù)列表匹配的 函數(shù)模板 "max" 實例參數(shù)類型為:(double, int)
  21. return 0;
  22. }

 2,、類模板

聲明了類模板,,就可以將類型參數(shù)用于類的成員函數(shù)和成員變量了。換句話說,,原來使用 int,、float、char 等內(nèi)置類型的地方,,都可以用類型參數(shù)來代替,。
類模板的一般形式:

當類中的成員函數(shù)在類的聲明之外定義時,它必須定義為函數(shù)模板,,帶上模板頭,,定義形式如下:

3,、模板的使用

 4、typename 和 class 的區(qū)別

在模板引入 c++ 后,,采用class來定義模板參數(shù)類型,,后來為了避免 class 在聲明類和模板的使用可能給人帶來混淆,所以引入了 typename 這個關(guān)鍵字,。

模板定義語法中關(guān)鍵字 class 與 typename 的作用完全一樣,。
不同的是typename 還有另外一個作用為:使用嵌套依賴類型(nested depended name)

  1. class MyClass
  2. {
  3. public:
  4. typedef int LengthType;
  5. LengthType getLength() const
  6. {
  7. return this->length;
  8. }
  9. void setLength(LengthType length)
  10. {
  11. this->length = length;
  12. }
  13. private:
  14. LengthType length;
  15. };
  16. template<class T>
  17. void MyMethod(T myclass)
  18. {
  19. //告訴 c++ 編譯器,typename 后面的字符串為一個類型名稱,,而不是成員函數(shù)或者成員變量
  20. typedef typename T::LengthType LengthType; //
  21. LengthType length = myclass.getLength();
  22. cout << "length = " <<length<< endl;
  23. }
  24. int main()
  25. {
  26. MyClass my;
  27. my.setLength(666);
  28. MyMethod(my);//length = 666
  29. return 0;
  30. }

十四,、命名空間和異常處理

1、命名空間

命名空間實際上是由用戶自己命名的一塊內(nèi)存區(qū)域,,用戶可以根據(jù)需要指定一個有名字的空間區(qū)域,,每個命名空間都有一個作用域,,將一些全局實體放在該命名空間中,就與其他全局實體分割開來,。
命名空間定義的一般形式:

 命名空間成員的引用:命名空間名::命名空間成員名
使用命名空間別名:namespace 別名 = 命名空間名
使用using聲明命名空間成員的格式:using 命名空間名::命名空間成員名;
使用using聲明命名空間的全部成員:using namespace 命名空間名;

using聲明后,,在using語句所在的作用域中使用該命名空間成員時,,不必再用命名空間名加以限定。
標準C++庫的所有標識符(包括函數(shù),、類,、對象和類模板)都是在一個名為std的命名空間中定義的,。
無名的命名空間,只在本文件的作用域內(nèi)有效,。

2,、異常處理

 

 

 

 十五,、STL

C++標準模板庫(Standard Template Library,STL)是泛型程序設計最成功的實例。STL是一些常用數(shù)據(jù)結(jié)構(gòu)和算法的模板的集合,,由Alex Stepanov主持開發(fā),于1998年被加入C++標準,。

C++ 標準模板庫的核心包括三大組件:容器,,算法,,迭代器

1、容器

順序容器:可變長動態(tài)數(shù)組Vector,、雙端隊列deque、雙向鏈表list
關(guān)聯(lián)容器:set,、multliset,、map、multimap

關(guān)聯(lián)容器內(nèi)的元素是排序的,所以查找時具有非常好的性能,。
容器適配起:棧stack,、隊列queu,、優(yōu)先隊列priority_queue
所有容器具有的函數(shù):

 順序容器和關(guān)聯(lián)容器函數(shù):

 順序容器獨有的函數(shù):

2,、迭代器

迭代器是一種檢查容器內(nèi)元素并遍歷元素的數(shù)據(jù)類型。C++更趨向于使用迭代器而不是下標操作,,因為標準庫為每一種標準容器(如vector)定義了一種迭代器類型,,而只用少數(shù)容器(如vector)支持下標操作訪問容器元素。按照定義方式分為以下四種,。

  • 正向迭代器:容器類名::iterator 迭代器名;
  • 常量正向迭代器:容器類名::const_iterator 迭代器名;
  • 反向迭代器:容器類名::reverse_iterator 迭代器名;
  • 常量反向迭代器:容器類名::const_reverse_iterator 迭代器名

3、算法

STL 提供能在各種容器中通用的算法(大約有70種),如插入,、刪除,、查找,、排序等,。算法就是函數(shù)模板。算法通過迭代器來操縱容器中的元素。
STL 中的大部分常用算法都在頭文件 algorithm 中定義。此外,,頭文件 numeric 中也有一些算法,。
許多算法操作的是容器上的一個區(qū)間(也可以是整個容器),因此需要兩個參數(shù),,一個是區(qū)間起點元素的迭代器,,另一個是區(qū)間終點元素的后面一個元素的迭代器。
會改變其所作用的容器,。例如:

  • copy:將一個容器的內(nèi)容復制到另一個容器,。
  • remove:在容器中刪除一個元素。
  • random_shuffle:隨機打亂容器中的元素,。
  • fill:用某個值填充容器,。

不會改變其所作用的容器。例如:

  • find:在容器中查找元素,。
  • count_if:統(tǒng)計容器中符合某種條件的元素的個數(shù),。
  1. #include <vector>
  2. #include <algorithm>
  3. #include <iostream>
  4. using namespace std;
  5. int main() {
  6. vector<int> v;
  7. v.push_back(1);
  8. v.push_back(2);
  9. v.push_back(3);
  10. v.push_back(4); //1,2,3,4
  11. vector<int>::iterator p;
  12. p = find(v.begin(), v.end(), 3); //在v中查找3 若找不到,find返回 v.end()
  13. if (p != v.end())
  14. cout << "1) " << *p << endl; //找到了
  15. p = find(v.begin(), v.end(), 9);
  16. if (p == v.end())
  17. cout << "not found " << endl; //沒找到
  18. p = find(v.begin() + 1, v.end() - 1, 4); //在2,3 這兩個元素中查找4
  19. cout << "2) " << *p << endl; //沒找到,指向下一個元素4
  20. int arr[10] = { 10,20,30,40 };
  21. int * pp = find(arr, arr + 4, 20);
  22. if (pp == arr + 4)
  23. cout << "not found" << endl;
  24. else
  25. cout << "3) " << *pp << endl;
  26. return 0;
  27. }

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多