C++ 基礎

C++

C++ 純編譯型語言,支持面向對象。html

兼容 C

基礎兼容性

  • 基本數據類型
變量 bool char short int void* long float double
內存 1 1 2 4 4 4/8 4 8
// C++ 存在基本的 bool 類型,不像 C,啥都沒有
// 這兩條語句是基本類似的
if(1){ cout<<true; }
if((bool)1){ cout<<true; }
/*
 * C/C++ bool 自動轉化規則
 * 0/NULL         --> false
 * number/(void*) --> true
 */

cin/cout 自己是一種流對象。ios

// 流對象支持指針或標準變量
cout<<"hello world"<<"!\n"<<endl;
cin<<b;
  • 變量控制
#define          //宏變量
static int a;    //靜態變量
extern int b;    //引入外部變量
register int c;  //寄存器變量
auto int e;      //默認塊變量

const int d;     //只讀變量
volatile int f;  //對變量施加內存屏障,訪問控制不走任何緩存
restrict int g;  //當前對象只有這一個引用可訪問,其餘全部引用皆無效

mutable      //存儲類,對象相關
thread_local //存儲類,線程相關
  • 運算符
/*
1. 算術運算符
2. 關係運算符
3. 邏輯運算符 ! && || 邏輯運算會自動短路
4. 位運算符
5. 賦值運算符
6. 其餘運算符

new : . >> << 等新增運算符。
 */
  • 流程控制
while(){}
for(){}     // for 第一次也會執行判斷
do{}while();
switch(){case: break; case: continue;}
if(){}
if(){}else{}
Exp ? Exp : Exp ; //簡化條件公式
  • 函數定義
// 函數定義沒啥好說的
void def(int a,int b){
    count<<a<<b<<endl;
}
// 函數參數默認值,必須知足最右參數默認原則
void def(int a,int b=1,int c=2){
    cout<<a<,b<<c<<a+b+c<<endl;
}
// def(0) def(0,1) def(0,1,2) 均可調用原始方法

// Lambda 函數表達式,這個語法糖好他媽醜
[capture](params)->{}
// 示例
[](int x,int y)->{return x+y;}

// 內聯函數,僅在最終須要時展開執行
inline int show(int a){
    return a*10;
}

// lambda inline 函數儘可能只保留簡單功能,邏輯不宜過於複雜
  • 數據結構
// 數組
int a[10][10];
// 結構體
typedef struct List{
    //...
}list;

// 位域結構體
typedef struct Step{
    //...
}step;

// 共用體
typedef union Buffer{
    //...
}buffer;

// 枚舉
// 可直接輸出,不可直接輸入,由於枚舉值是標識符常量
typedef enum Socre{
    //...
}score;

特性兼容性

  • 函數傳參
// 值傳遞,copy副本
// 沒法修改原始參數
void show(int val){
    cout<<val++<<endl;
}

// 址傳遞,地址副本
// 可修改原始指針空間的值,以及指針
void show(int* val){
    cout<<(*val)++<<endl;
}

// 引用傳遞,引用副本
// 可修改原始參數
void show(int& val){
    cout<<val++<<endl;
}
  • string
// C++ 字符串類
#include<cstring>
string str = "hello world";
// 字符串長度
int len = str.size();

cout<<"hello"<<" world"<<endl;

string str = str.substr(0,str.size());
str = str +str;

string a = "abc";
string b = "adc";

// 比較兩個 string 對象時可用,基本 邏輯運算符
cout<<(a == b)<<endl; // 1 0
// 比較字符串對象與字符串時
cout<<a.compare("abc")<<endl;
  • 內置庫
// 至關於stdlib.h
#include<iostream>
// 數學方法函數
#include<cmath>
// 時間函數相關
#include<ctime>
// 不知道什麼庫
#include<cstdlib>

// 10位時間戳
cout<<time(NULL);
// 設置隨機種子爲當前 10位時間戳
srand((unsigned)time(NULL));
cout<<rand();

floor(3.6);  -> int  3;
floor(-3.6); -> int -4;
ceil(3.6);   -> int  4;
ceil(-3.6);  -> int -3;

round(); // 精度
log();   // ln()
log10(); // log10
  • IO
# include<iostream>
// 標準輸出流,默認屏幕
cout<<"hello world"<<endl;

int a,b;
// 標準輸入流,一次可執行多個
cin>>a>>b;

// 標準錯誤流,默認屏幕,會當即輸出到屏幕
cerr<<"error"<<endl;
// 標準日誌流,默認屏幕,存在緩衝區,緩衝區滿了則刷新一次
clog<<"log"

// C++ 標準文件庫,能夠直接用 C 的標準文件庫
#include<fstream>
  • 指針與引用
/*
 C 中的變量地址,能夠拿出來,也能夠利用地址強制指針化
 C++ 中的變量地址,僅是可讀的,可是拿不出來,更安全,但卻少太多靈活性
 */

// C
int i  = 100;
int ad = &i;   // 這裏能夠直接取到變量的實際內存地址

// C++
int i  = 100;
int ad = &i;   // C++ 把這一步閹割了,&i 是可讀的,但沒法賦值於其餘變量

// C++ 引用,別名
int i  = 100;
int& j = i;    // 此時 i j 僅表明一個變量,別名系統

int* p = &j;   // i j 均可以取到指定的地址
  • 異常處理

throw try-catch。
C++ 異常處理與 Java 很是類似。
http://www.javashuo.com/article/p-rhrpvurf-bq.htmlc++

// 異常頭文件
#include<exception>

// try-catch 語句塊
try{
    if(true){
        // 主動拋異常
        throw 10;
    }
// 捕獲異常
}catch(int e){
    cout<<i<<endl;
}
cout<<"hello world"<<endl;

// 自定義異常類型
class MyException:public exception{
    virtual const char* what() const throw(){
        return "MyException pass!";
    }
}myexception; // 別名? c++ 搞得好亂
  • 內存管理
int* p = NULL;

// C++ new-delete 內存管瘤
p = new int;
delete p;

// C malloc-free 內存管理
p = (int*)malloc(sizeof(int));
free(p);

// C++ new   申請一個對象空間,delete 釋放一個對象空間
// C malloc 申請指定大小的空間,free 釋放指針指向的空間
  • 命名空間

C++ namespace 搞的有點垃圾。不如 Java 靈活。數組

// 自定義命名空間
namespace first{
    void show(){
        cout<<"first-show"<<endl;
    }
}

// 使用 first.show() 方法
first::show()

// 加載命名空間,內部成員可直接使用,必須知足過程式結構
using namespace first;

// 可直接使用
show();

// 命名空間可嵌套定義,感受做用不大
namespace second{
    namespace sec{
        int i = 100;
    }
}
// 使用嵌套內部成員
second::sec::i;
  • 模板成員

C++ 模板系列,就是 Java 的泛型。
C++ 泛型類雙邊必須都存在類型的定義,Java僅須要一邊的。緩存

// 泛型-函數
template <typename T> void show(T param){
    cout<<param<<endl;
}
// 泛型-類
template <class T> class Exp{
    T p;
    public:
        show(){
            cout<<this->p<<endl;
        }
}
// 使用泛型類
Exp<int>(1000).show();
Exp<int> p = Exp<int>(1000);
p.show();
  • 指針使用
$關鍵點$ $解決方法$
指針定義 指針定義完成後,指向隨機棧地址;需初始化null
指針釋放 除非還存在指向這片內存的指針,不然必須釋放堆內存
內存 任何地方,堆內存只能主動申請,主動釋放
內存指針 儘可能不要多指針指向同一片內存,易出現異常
內存申請 某些場景下,需判斷內存是否申請成功
內存釋放 內存被釋放後,指針依然可強制訪問,需設指針爲null
函數參數 某些場景下,參數須要判斷null
函數返回 函數僅能返回主動申請內存的指針,局部變量值
內存嵌套 嵌套的結構只能從最內層向外層遞歸釋放
內存數組 數組內使用堆內存還好,主要是當心下標越界問題
內存結構體 內部存在遞歸關係時,須要謹慎使用堆內存

面向對象

基礎特性

  • 類特性
class Exp{
    int x;
    int y;

    // 靜態,類級別變量,但依然受限於權限控制符
    static int sta;
    // 只讀,初始化對象,或定義時即完成初始化
    const int con = 100;
    // 引用,初始化對象時,或定義時即完成初始化
    int &y = x;

    // this 可訪問對象級別的全部成員
    // this 沒法訪問類級別成員,static 靜態成員 Exp.sta sta 便可訪問
    public:
        // 預約義方法,參數定義有兩種
        int show(int x,int y);
        show(int);
}; // class 結尾必須加 ;用以結束語句塊
// 實現預約義的具體方法
Exp::show(int x,int y){
    return x+y;
}
Exp::show(int param){
    cout<<param<<endl;
}

/*
    C++ 繼承特性,private成員沒法被繼承,支持多重繼承
    public    繼承父類 public->public,protected->protected
    protected 繼承父類 public/protected -> protected
    private   繼承父類 public/protected -> private

    vittual  虛擬繼承 What Fuck!
 */
  • 成員特性
// 成員訪問控制
class Exp{
    public:
        // 類-友元,子類,類外部
    protected:
        // 類-友元,子類
    private:
        // 類-友元
};

// 默認成員訪問控制
class Exp{
    // 全部成員默認 private
    // 成員變量,默認私有
    int x;
    // 成員函數,默認私有
    void show(){
        cout<<"hello world"<<endl;
    }
};
  • 友元特性
// 友元,單向特性,擁有當前類的全部訪問權限
class Exp{
    int x;
    // 此處申明指定類, 爲本類的友元類
    friend class demo;
    // 此處申明指定函數,爲本類的友元函數
    friend void show(Exp);
}

// 友元類
class Demo{...}

// 友元方法
void show(Exp exp){
    // 可直接訪問私有成員
    cout<<exp.x<<endl;
}
  • 構造特性
class Exp{
    int x;
    public:
        // 構造函數,建立對象時執行
        Exp(int x){
            this->x = x;
        }
        // 基於重載特性,深拷貝函數
        Exp(const Exp obj){
            this->x = obj.x;
        }
        // 析構函數
        ~Exp(){
            // 釋放對象內存時執行
        }
    /*
      類繼承時
      構造函數:父類執行,子類再執行
      析構函數:子類執行,父類再執行
     */
}
  • 重載特性
// 重載,函數同名但參數不一樣,則視爲不一樣函數
class Exp{
    int x;
    public:
        Exp(int x){
            this->x = x;
        }
        // C++ 支持,函數重名,
        void show(){
            cout<<"hello world"<<endl;
        }
        void show(int params){
            cout<<params<<ednl;
        }
    // 另外一種,運算符重載 =,賦予運算符特殊功能
    Exp operator=(const Box& b){
        //...
        return null;
    }
}
  • 覆蓋特性
// 子類可覆蓋父類中同名成員(包括變量,函數)
class Exp{
    public:
        void show(){
            cout<<"Class Exp"<<endl;
        }
};
class Demo:public Exp{
    public:
        void show(){
            cout<<"Class Demo"<<endl;
        }
};

Exp().show();
Demo().show();
  • 對象特性
// 結構體方式建立對象,不推薦使用
Exp exp(1,2,3);                // 默認內存管理
// 標準對象建立方式,非堆內存對象,推薦使用
Exp exp = Exp(1,2,3);          // 默認內存管理
// 標準對象建立方式,堆內存對象,推薦使用
Exp* exp = new Exp(1,2,3);     // 主動內存管理,new delete 管理對象內存

// 對象引用複製
Exp& ex = exp;
// 對象指針複製,不推薦使用,多指針指向一個對象,內存管理很是麻煩
Exp* = &exp;

// 標準對象訪問模式
exp.show();
// 指針對象訪問模型
exp->show();

// 快捷方式
Exp(1,2,3).show();
new Exp(1,2,3)->show();

抽象特性

  • 面向對象設計差別
C++ Java
static控制 static控制
權限 3P原則,友元 3P原則
構造 構造析構,深拷貝 構造,GC回收,深拷貝,clone接口
繼承 n,3P原則,都成爲子類的成員 1,public,子類與父類嚴格區分
覆蓋 子類可覆蓋父類的變量、函數 子類可覆蓋父類的函數
重載 重載函數,運算符重載 重載函數
對象 引用、指針,可快捷化 引用,可快捷化
  • 抽象設計
  1. 抽象類,存在一個或以上的 virtual所修飾的抽象方法。
  2. 接口,某個抽象類中只有 virtual 所修飾的抽象方法。
  3. 抽象類、接口,沒有嚴格的設計區分,需自行設計。
  4. 抽象類、接口,都不能直接實例化,必須由實現類實現抽象方法後纔可以使用。
class Exp{
    public:
        // 純虛函數,就是Java中的抽象方法
        virtual void show() = 0;
};
class Demo:public Exp{
    public:
        // 子類實現父類的抽象方法
        void show(){
            cout<<"hello world"<<endl;
        }
};
// C++ 的抽象類:存在一個以上的純虛函數
// C++ 的接口類:內部僅存在純虛函數
// C++ 抽象系列與 Java 系列沒什麼差異

高級特性

容器特性

  1. 容器自己是一種數據結構,內部數據類型自定義。
  2. 注意一下容器迭代器,以及自己特性。
  • vector
#include<vector>

// 本質上就是一個數組,但支持動態擴容
// 開始時,申請一塊內存,擴容時釋放原內存,申請新內存便可

vector<int> arr = {1,2,3,4,5,6};
vector<int> arr(10,0);
cout<<arr[0]<<arr[5]<<endl;

arr.push_back(10);
arr.pop_back();
arr.size();

stack<int> sta;
sta.push(1);
sta.pop();

unordered_set<string> set;
set.insert("hello world!");
  • deque
#include<deque>

// 本質上就是一個雙端隊列,但其隊列頭、尾的插入刪除很是塊。
  • list
#include<list>

// 雙向鏈表,插入、刪除快,隨機訪問比較慢。
  • map
#include<map>

// 映射集合 key:value,內部自建一個紅黑樹
  • set
#include<set>

// 集合,不容許重複,內部自建紅黑樹

多線程-鎖

相關文章
相關標籤/搜索