C++自學筆記

2020-08-08 21:43:12

筆記整理自菜鳥C++教學

一、C++基本特徵

物件導向,區分大小寫

二、標頭檔案書寫

寫法:include<>include""

stdio.h/iostream.h/iostream的區別

  • stdio.h是C的標準I/O庫,iostream.h是C++非標準輸入輸出流,iostream是C++標準輸入輸出流。
  • iostream.h繼承C語言的標準庫檔案,未引入命名空間,輸出直接參照cout<<x;
  • iostream引入cout的兩種方法:using namespace std; cout<<x;或using std::cout; cout<<x;

三、名稱空間:using namespace std;

  • 標準庫裡的名字都加上 std:: 的字首,你必須用std::vector來參照vector類。寫上上述句子可以不用寫字首直接寫vector。
  • 名稱空間爲變數或函數等實體定義範圍
  • 定義名稱空間:namespace名稱空間名{}
  • 呼叫名稱空間中函數:名稱空間名::函數名();
  • using指令:使用 using namespace指令,這樣在使用名稱空間時就可以不用在前面加上名稱空間的名稱。故std也是名稱空間

四、變數

  • 變數宣告:extern

五、常數

  • 用大寫字母表示常數
  • 常數定義:#define或const關鍵字

六、儲存類

  1. static:區域性變數,檔案內全域性變數
  2. extern:所有檔案可見變數
  3. thread_local:執行緒內變數

七、函數參數傳遞

  1. 值:i—>j,實參i,形參j,i賦值給j
  2. 指針:&i—>int *j,實參i,形參j,j是i的指針
  3. 參照:i—>int&j,實參i,形參j,i和j相同
  4. 陣列的參數傳遞:實參數組名—>int 形參數組名,陣列長度常數—>int i

指針的理解: int* 用來定義指針,定義int * j,定義賦值int* j=&i,賦值j=&i。理解上int和* 在一起,寫法上* 指針名在一起。
參照的理解: &僅表示參照,定義賦值int& j=i。理解和寫法都是int和&在一起。`

八、字串

  • C風格字串:char 陣列名={‘w’,‘e’,‘\0’}或「we」
    • 字串函數:strcpy(s1,s2)//複製,strcat(s1, s2)//連線,strlen(s1)//長度,strcmp(s1, s2)//比較大小
    • 字串指針p,* p爲第一個元素,* (p+1)爲第二個元素
  • C++中的String類
    • #include <string>
    • string str1 = "Hello";
    • =複製,+連線

九、結構體

  • 宣告方法1:stuct 結構體型別名{};
  • 宣告方法2:typedef struct 結構體型別名{}結構體型別名;
  • 結構體和類的宣告,大括號後有分號,而函數沒有
  • 指向結構的指針:宣告和賦值同其他,呼叫結構體中成員用->

十、時間

  • #include <ctime>
  • time_t 變數名 = time(0);該函數返回系統的當前日曆時間,自 1970年1月1日以來經過的秒數。

十一、基本輸入輸出

標頭檔案: <iostream>

標準輸出流cout,流插入運算子 <<
cout << "Value of str is : " << str << endl;

  • <<可以多次使用,str爲字串變數名或字元陣列名,end1爲換行符
  • 在正式輸出前使用cout方法修改輸出格式

標準輸入流cin,流提取運算子 >>
char str[50];cin >> str;

  • 「>>」可使用多次,相當於多行合併
  • C++ 輸入多個字元,中間用一個字元隔開,cin.get()是可以忽略掉一個字元的:cin>>a;cin.get();cin>>b;

cin的方法
cin.getline(str,50);代替cin>>str;
新增cin.ignore()到cin>>str後會忽略掉之前讀語句留下的多餘字元

標準錯誤流cerr,<<
cerr 物件是非緩衝的,每個流插入到 cerr 都會立即輸出

標準日誌流clog,<<
clog 物件是緩衝的,每個流插入到 clog 都會先儲存在緩衝區,直到緩衝填滿或者緩衝區重新整理時纔會輸出

十二、類和物件

  • 類就是模型,物件就是按照模型打造的複數實體
  • 定義類:class 類名{類主體}
  • 定義物件:類名 物件名
  • 類存取修飾符:預設是private 的,除繼承型別的寫法和Java一致寫在同行最前外,其餘寫法(成員變數和成員函數)如下
    在这里插入图片描述

12.1 類的函數

  • 分類:成員函數,建構函式(特殊的成員函數),解構函式(特殊的成員函數)
  • 宣告:類裏面正常宣告,類外定義的函數名爲:類名::函數名
  • 有關成員函數中變數的宣告都在類中宣告

類建構函式

  • 建立類的新物件時執行,函數名和類名相同,不反回任何型別包括void,可在類中宣告並在類外定義或者不寫。class line{line();};
  • 預設構造參數沒有參數,函數定義爲line:line(void),可帶參數。這裏帶參數的建構函式不需要像Java前置不帶參數的建構函式。沒寫建構函式則系統生成預設建構函式。
  • 建立物件:類名 物件名(無參)類名 物件名(參數)(含參)
  • Java和C++物件導向的區別:Java主函數名爲檔名而C++爲int main(),Java建立物件要new建構函式並且寫法也不同,Java成員函數定義寫類裏面而C++成員函數宣告寫類裏面定義寫類外面,Java所有函數都是類的成員函數而C++則是獨立函數和成員函數混用,Java成員函數中物件的參數需要用this.而C++直接寫變數,Java一般通過建構函式給物件新增參數而C++可以通過其他成員函數一個一個給物件新增參數此時類裡的一套變數獨立出來

類解構函式

  • 刪除物件時執行(這個刪除是程式結束預設執行的),和建構函式同,函數名前加~
  • 類構造和解構函式的特殊就是主動性,至於內容可以複製也可以僅輸出。

拷貝建構函式

  • 物件初始化方式:建構函式/物件賦值(使用拷貝建構函式)

友元函數

  • 獨立定義的函數,在類中用friend 函數名來宣告,該函數可以直接存取該類的任何成員
  • 友元不是類的成員,沒有this指針

this的使用

  • 用於參數爲物件的成員函數,因爲成員函數需要物件來使用,則爲box1.compare(box2),this指代box1即呼叫物件
  • 建構函式不使用
  • this->

12.2指向類的指針

使用同結構體

12.3類的靜態成員

static宣告,靜態成員在類的所有物件中是共用的

十三、C++物件導向

13.1 繼承

  • 定義:class 派生類名:public 基礎類別名
  • 派生類繼承所有非private成員,繼承所有基礎類別方法除建構函式、解構函式、拷貝建構函式、過載運算子、友元函數
  • 繼承型別:公有繼承public原樣繼承,保護繼承protected基礎類別的共有成員降級爲保護成員,私有繼承同上類推全部降級爲私有成員
  • 多繼承:一個子類可以有多個父類別,多組繼承型別基礎類別名間用逗號隔開

13.2 過載

函數/運算子多個定義,不同定義的參數不同

13.3 多型

  • 繼承基礎類別的派生類中重寫基礎類別的函數,則會無效
  • 在基礎類別中對應函數整體前加virtual則執行派生類的函數,這種函數被稱爲虛擬函式(在基礎類別中)
  • 純虛擬函式:無實體的虛擬函式,宣告-virtual 返回值 函數名() = 0;
  • 虛擬函式的過載性和它宣告的許可權無關,因爲過載之時並沒有與父類別發生任何的呼叫關係,故而過載是被允許的。
  • 介面/抽象類
    • 如果類中至少有一個函數被宣告爲純虛擬函式,則這個類就是抽象類。
    • 設計抽象類的目的,是爲了給其他類提供一個可以繼承的適當的基礎類別。抽象類不能被用於範例化物件,它只能作爲介面使用。

十四、檔案和流

標頭檔案<iostream><fstream>

14.1 數據型別/類

  • ofstream輸出檔案流,建立檔案並寫入
  • ifstream輸入檔案流
  • fstream檔案流,同時具備輸入輸出

14.2 開啓檔案

宣告物件,使用物件中的open方法
第一個參數爲檔名稱和位置,用雙引號
第二個參數爲檔案被開啓的模式,多模式用 | 分隔

ios::app追加至檔案末,ate定位至檔案莫,in開啓檔案用於讀取,out開啓檔案用於寫入,trunc若檔案存在其內容被截斷即檔案長度爲0

14.3 關閉檔案

方法close();

14.4 寫入檔案

用ofstream/fstream的物件(其本身是類,物件是該檔案),<<,同cout物件

14.5 讀取檔案

用ifstream/fstream的物件,>>,同cin物件

14.6 檔案位置指針(本身是方法)

檔案位置指針:seekg(長整型,定位元型樣)
定位元型樣:不寫預設從頭開始,ios::cur當前位置,end末尾

十五、例外處理

  • try:它裏面放置可能引發異常的程式碼,不寫用來觸發異常的程式碼
  • 正常執行try中程式碼,try中程式碼出現異常,系統自動生成一個異常物件,尋找能處理該異常的catch塊,通過catch後的異常型別識別

十六、動態記憶體

記憶體分爲兩個部分
棧:在函數內部宣告的所有變數都將佔用棧記憶體。
堆:這是程式中未使用的記憶體,在程式執行時可用於動態分配記憶體。

16.1 分配記憶體

一般是通過指針爲指針指向的變數分配記憶體,此時指針一般初始化爲NULL,即=NULL。

16.2 動態分配記憶體

所需記憶體大小需要執行時才能 纔能確定

16.3 new分配記憶體,delete回收記憶體

  • new:指針宣告後,指針名 = new 變數型別;
  • delete:delete 指針名;
  • new 與 malloc()函數相比,其主要的優點是,new不只是分配了記憶體,它還建立了物件。且malloc一般需要sizeof()來確定大小,並且強制型別轉換成對應型別指針。

16.4 陣列的動態記憶體分配

  • new:指針宣告後,指針名 = new char[20];
  • delete:delete [] 指針名;
  • 二維陣列:for回圈,三維陣列:雙重for回圈

16.5 物件的動態記憶體分配

  • new:將指針宣告和分配記憶體合一。Box *指針名 = new Box;
  • 這裏和Java物件建立非常像,同時建構函式被呼叫。只是Java中new後面跟的就是建構函式,有(),而C++沒有。
  • 物件陣列即Box*指針名 = new Box[4];

十七、模板

十八、前處理器

十九、信號處理

  • 信號名包括:SIGINT、SIGABRT、SIGFPE、SIGILL、SIGSEGV、SIGTERM、SIGHUP,信號名對應信號編號

  • 函數呼叫:signal(SIGINT信號名, signalHandler信號函數名);
    signal函數

    • 定義:void signalHandler信號函數名( int signum信號編號)
    • 函數體內有終止:exit(sigum信號編號)
  • 觸發信號:ctrl c或raise(SIGINT信號函數名);用於生成信號

二十、多執行緒

標頭檔案:#include <pthread.h>

20.1 建立執行緒

先定義執行緒變數,多個變數使用陣列。pthread_t 執行緒名
執行緒建立函數

  • 參數依次是:建立的執行緒名,執行緒參數,執行緒執行函數,執行緒執行函數參數

  • int ret = pthread_create(&tids[i], NULL, say_hello, NULL);

  • if (ret != 0)

  • ret用於判斷和處理建立失敗

執行緒退出

  • pthread_exit(NULL);一個退一組

20.2 執行緒傳遞參數

  • 實參:(void*)&變數名,地址進行強制型別轉換成空指針
  • 形參:void *新變數名,空指針
  • 函數中建立一個對應變數型別的指針變數,將形參轉換爲對應變數型別的指針並賦值給剛建立的指針
  • 此方法同用於所有以結構體作爲實參的傳遞