C++_學習筆記

 

C++
面向對象特徵:封裝——抽象——繼承——多態
https://www.runoob.com/

<命名空間>
——————————————————————————————————————————————————————————————————————————————————————————
#include <iostream>
1    using namespace std;
2    using std::變量;
3    std::變量;

    cout  cin

定義:
namespace  spaceA{
    int a = 10;
    namespace spaceB{
        struct std{
            int age ;
        }    
    }
}

使用:
using namespace spaceA;
using spaceA::a;
spaceA::a;


<bool加強>
——————————————————————————————————————————————————————————————————————————————————————————
bool a = true ; 1
bool b = false; 0

sizeof(a) = 一個字節;


<三目加強> 
——————————————————————————————————————————————————————————————————————————————————————————
c = a < b ? a : b

(a<b?a:b = 10)
三目運算符能夠當左值;c不行!

<const加強>
——————————————————————————————————————————————————————————————————————————————————————————
const int a == int const a  (const編譯器階段,宏是在預處理階段)必須初始化
(C語言:a能夠經過指針改變,因此a爲假常量,如:int arr[a] 報錯!)
(C++:a不能夠經過指針改變,因此a爲真常量,如:int arr[a],正常!)
const int * a  
int* const  a
const int* const a 


<枚舉加強>
——————————————————————————————————————————————————————————————————————————————————————————
enum nu {
    aa,
    bb,
    cc,
};

enum nu p = aa;(只能賦值枚舉類型!)




<inline 內斂函數>
——————————————————————————————————————————————————————————————————————————————————————————
函數:不斷的壓棧出棧,再壓棧出棧,開銷比較大。(解決宏的弊端!)
    
    
宏:預處理階段展開;不須要壓棧出棧,弊端數據不處理。
        
        
內聯函數:編譯器階段展開;不須要壓棧出棧,
    本質:犧牲代碼段空間爲代價,提升運行的時間效率;
    特色:定義聲明加inline
          c++編譯器將函數體直接插入到被調用的地方;
          沒有普通函數調用時的開銷(壓棧,跳轉,返回)
    弊端:函數不能龐大,循環,判斷,取址
          

<引用>
——————————————————————————————————————————————————————————————————————————————————————————
int a = 1;
int &aa = a;(引用實質爲常指針,變量的別名!) == int *const aa = a;

1.聲明必須初始化;
2.&前有類型爲引用,其餘皆爲取址
3.可對引用再次引用,屢次引用只是取別名
4.引用於變量地址相同

 
引用於函數:
int& fun(int& a);
1.作函參(不須要拷貝動做)
 
2.作返值(不須要拷貝動做)
  能夠做爲左值!由於返回值爲引用(別名)

引用於結構:(不須要值拷貝)
struct info{
    int age;
};
const info& fun(info &a);


引用於指針:(用於簡化指針)


引用類對象:


引用於const:
    const int a = 1;
    const int& aa = a;

    int b = 1;
    const int& bb = b;





<函數默認佔位參數>
——————————————————————————————————————————————————————————————————————————————————————————
默認參數:定義函數參數直接賦值,默認起始從右至左 !

佔位參數:沒什麼意義!




<函數重載>
——————————————————————————————————————————————————————————————————————————————————————————
函數重載:函名相同,函參不一樣,缺一不可!
    注意:函數重載,不要寫默認參數,避免函數衝突!
          類型嚴格匹配,不匹配隱式轉換,字符串不行!

    編譯器:void fun(char a,int b) --> fun_ci
    
    
    與函數指針:typedef int(fun)(int,int);  fun *pfun;
                typedef int(*fun)(int,int); fun pfun;
                int (*fun)(int,int)=NULL;
                
    函數指針經過形參匹配函數重載(指向匹配函數),自身不能重載!
    
1.函數指針指向成員函數存在this指針不成功,靜態成員函數沒有this指針!
2.重載函數在本質上是相互獨立的不一樣函數。
    

<類與對象>
——————————————————————————————————————————————————————————————————————————————————————————
類的機制後實現了數據的隱藏與封裝,類的成員變量通常定義爲私有成員,成員函數通常定義爲公有的,依此提供類與外界間的通訊接口

類: 成員函數   ->   對象     //(當作升級版的結構體 !)
     成員變量

封裝:對外開放數據,屏蔽數據,提供接口
      將屬性方法進行封裝,進行訪問控制
      public protected private        //(後兩個僅在繼承的時候纔有區別!)


class Data{             //(內部訪問)
public:
    void init(void);
private:
    int year;
    int mon;
    int day;
}
    Date one;
    one.init();

struct 默認全部成員爲 public 
class  默認全部成員爲 private

#類的get方法:int  getter(){ return a ;}
#類的set方法:void setter(int new){ a = new ; }

1.類加上一個加強版的結構體


<構造與析構>
——————————————————————————————————————————————————————————————————————————————————————————
構造:類中定義與類名相同的特殊成員函數,叫作構造函數 (定義馬上初始化,避免危險!)
    類名();
    
    自動調用:通常c++編譯器自動調用,特殊狀況手動調用;

    
    分類:
        有參:
        class stu{
        public:
            stu(int a){
                age = a;
            }
        private:
            int age;
        }
        stu t(6); // 建立直接初始化,避免危險!
                
        無參:
        拷貝:深拷貝  淺拷貝    
        
            拷貝:class 類名{
                    類名(const 類名 & another){    //const保護被拷貝值!
                    拷貝結構體
                    }
                  }
            類名 t ;
            類名 t1(t);  //t給t1拷貝初始化 (類沒有定義,系統默認提供,兩個如出一轍!)
            == 類名 t2 = t ;       //屬於構造拷貝(無參初始化)
           !== 類名 t3 ;t3 = t ; // 沒有在初始化進行,不是拷貝屬於賦值
         
         默認:
               默認無參構造函數:當類中沒有定義構造函數時,編譯器默認提供一個無參構造函數,而且其函數體爲空
               
               默認拷貝構造函數:當類中沒有定義拷貝構造函數時,編譯器默認提供一個默認拷貝構造函數,簡單的進行成員變量的值複製

                深拷貝:
                淺拷貝:
                
        初始化列表:
            

重點:
1.無返無參,類名相同,可重載,可默認參,一經實現,默認不復存在
2.對象建立時自動調用,完成初始化工做!
3.若是類中自定義構造函數,對象定義必須初始化!
4.顯示提供構造函數,默認構造不存在;不提供默認構造自動調用,什麼都不幹!
5.顯示拷貝構造不存在時!系統提供默認拷貝構造函數,將拷貝值如出一轍複製;(如:拷貝:)
6.沒有任何顯示構造函數(顯示無參,有參,拷貝)時,系統默認構造纔出現
7.當自定義構造函數時,定義對象的同時必須進行初始化!!!
8.構造對象成員的順序跟初始化列表無關,跟定義順序有關
9.對象的初始化只能經過構造函數!

    
析構:對構造函數進行清理    //(構造函數臨死以前,系統自動調用析構函數)
    ~類名();        // 如:構造函數new,棧空間回收以前調析構回收堆空間,防止內存泄露
    
    默認:同理
          默認無參析構函數:當類中沒有定義析構函數時,編譯器默認提供一個無參析構函數,而且其函數體爲空

重點:
1.無類型無參無返,不可重載!和默認參
2.每一個類只能有一個析構
3.構造new,析構delete
4.提供顯示析構,默認析構不存在!
5.有垃圾寫析構,無垃圾不用寫,只是系統提供的接口!
6.析構調用與構造順序相反!誰先構造,誰後析構!!(棧原理:先進後出,壓棧彈棧)


<動態建立/釋放 new/delete>
——————————————————————————————————————————————————————————————————————————————————————————
形式:指針變量 = new 類型(常量)   // ()初始化空間!
      指針變量 = new 類型 [表達式]  
      
      delete   指針變量
      delete[] 指針變量

做用:從堆空間分配一塊類型大小存儲空間,返回首地址
      常量爲初始化值,可省略;數組對象不能指定初始值

重點:
1.malloc和free是庫函數(Cpp建議不要用)
2.new和delete是運算符,不是函數,所以執行效率高(不是函數,不用壓棧彈棧)
3.malloc不會觸發類的構造函數,而new會觸發類的構造函數
4.Free不會觸發類的析構函數,而delete會觸發類的析構函數




<靜態>
——————————————————————————————————————————————————————————————————————————————————————————
靜態成員變量:
    
  聲明:  static 數據類型 成員變量;    //在類的內部
  初始化:數據類型 類名::靜態數據成員=初值;//在類的外部
  調用:  類名::靜態數據成員
          類對象.靜態數據成員        
      

靜態成員函數:

  聲明:static 函數聲明  //在類的內部
  調用:類名::函數調⽤用
        類對象.函數調⽤用

靜態成員函數只能訪問靜態數據成員。 緣由:非靜態成員函數,在調用時this 指
針被看成參數傳進。而靜態成員函數屬於類,而不屬於對象,沒有 this 指針。


#編譯器對屬性方法的處理機制:
    靜態存儲空間:
    處理機制:成員變量和成員函數是分開存儲!
        成員變量:
                普通:存儲於對象中,與struct變量有相同的內存佈局和字節對齊方式
                靜態:存儲於全局數據區中(在類裏面)
        成員函數:存儲於代碼段    


重點:
1.C語言中的內存四區模型仍然有效!
2.CPP中類的普通成員函數都隱式包含一個指向當前對象的this指針。!!!
3.靜態成員函數、成員變量屬於類!!!
4.靜態與普通成員函數的區別:
    靜態成員函數不包含指向具體對象的指針
    普通成員函數包含一個指向具體對象的指針
5.靜態成員函數沒有this指針,能夠經過函數指針指向!
6.Cpp靜態成員屬於整個類而不是某個對象,靜態成員變量只存儲一份供全部對象共用
7.全部對象均可以共享它,使用靜態成員變量實現多個對象之間的數據共享不會破壞隱藏的原則,保證了安全性還能夠節省內存!
8.類的靜態成員,屬於類,也屬於對象,但終歸屬於類!
9.static成員只能類外初始化



<this指針>
——————————————————————————————————————————————————————————————————————————————————————————
成員函數隱含定義this指針,接受調用對象的地址,指向調用對象;

#類成員函數形參和類屬性,名字相同,經過this指針解決
#類成員函數可經過const修飾


1.把全局函數轉化成員函數,經過this指針隱藏左操做數
  Test add(Test &t1,Test &t2) -> Test add(Test &t2)

2.把成員函數轉換全局函數,多了一個參數
  void prit() -> void prit(Test *pthis)

3.函數返回元素和返回引用

如圖:


1.類定義對象時,私有成員被分配,公有函數接口經過調用者的地址進行操做
2.this就是當前調用函數對象的地址!
3.this指針不是const text* 類型 
4.this指針是一個常指針,是 text const * 類型(只能指向對象自己!能夠改變值,不可改變址!)
5.int getk() const :修飾this指針爲const text const * 只讀



<友元>
——————————————————————————————————————————————————————————————————————————————————————————
#同類對象間無私處,異類對象間有友元!

友元三友:
  友元函數
  友元類
  友元成員函數
    
詮釋:類的機制後實現了數據的隱藏與封裝,類的數據成員通常定義爲私有成員,成員函數通常定義爲公有
      的,依此提供類與外界間的通訊接口。可是,有時須要定義一些函數,這些函數不是類的一部分,但又
      須要頻繁地訪問類的數據成員,這時能夠將這些函數定義爲該函數的友元函數。除了友元函數外,還
      有友元類,二者統稱爲友元。

做用:提升了程序的運行效率,但它破壞了類的封裝性和隱藏性,使得非成員函
      數能夠訪問類的私有成員。


友元函數:能夠直接訪問類的私有成員的非成員函數。它是定義在類外的普通函數,它不屬於任何類,但須要在類的定義中加以聲明,聲明時只需在友元
          的名稱前加上關鍵字 friend

        friend 類型 函數名(形參)  //一個函數能夠是多個類的友元函數,只須要在各個類中分別聲明。
        
        全局函數做友元函數;
        類成員函數做友元函數
        
1.全局函數做爲友元函數
2.成員函數做爲友元函數


友元類  :友元類的全部成員函數都是另外一個類的友元函數,均可以訪問另外一個類中的隱藏信息

#當但願一個類能夠存取另外一個類的私有成員時,能夠將該類聲明爲另外一類的友元類

        friend class 類名;(類名必須是程序中已定義的類)

注意:
1.友元關係不能被繼承
2.友元關係是單向的,不具備交換性(若類B是類A的友元,類A不必定是類B的友元,要看在類中是否有相應的聲明)
3.友元關係不具備傳遞性(若類B是類A的友元,類C是B的友元,類C不必定是類A的友元,一樣要看類中是否有相應的聲明。)
4.元友函數沒有this指針


<重載>
——————————————————————————————————————————————————————————————————————————————————————————
#所謂重載,就是從新賦予新的含義!!!

本質:運算符重載的本質是函數重載

重載函數:

    函數類型 函數名 operator 運算符名稱(形參表列){     
        重載實體;    
      } //operator 和 運算符名稱(一塊兒構成了新的函數名)== operator+重載了運算符+  
      //函數名是由 關鍵字operator和其後要重載的運算符符號構成的
    const Complex operator+(const Complex &c1,const    Complex    &c2);
    operator+ 重載了運算符+


友元重載:
成員重載:


操做符重載:
    
    關係重載:>, <, ==, >=, <=, !=
    邏輯重載:|| && !
    賦值重載:=
    單目重載:+ - * &
    雙目重載:+ - * / %
    位運算重載:& | ~ ^ << >>
    自增減重載:++ --
    申請釋放重載:new new[] delete delete[]
    輸入輸出重載:
    其餘運算重載:()函數調用 ->成員訪問 ,逗號 []下標

不可重載:
    成員訪問:.
    成員指針訪問:.* ->*
    長度:sizeof
    條件:?:
    域運算:::
    預處理: #

重載規則:
1.Cpp不容許用戶本身定義新的運算符,只能對已有的Cpp運算符進行重載。
2.Cpp容許重載的運算符 如圖:
3.重載不能改變運算符運算對象(即操做數)的個數    
4.重載不能改變運算符的優先級別。
5.重載不能改變運算符的結合性
6.重載運算符的函數不能有默認的參數
7.重載的運算符必須和用戶定義的自定義類型的對象一塊兒使用,其參數至少應有1個是類對象(或類對象的引用)
8.用於類對象的運算符通常必須重載,但有兩個例外,運算符=和運算符&沒必要用戶重載
9.應當使重載運算符的功能相似於該運算符做用於標準類型數據時候時所實現的功能
10.運算符重載函數能夠是類的成員函數,也能夠是類的友元函數,還能夠是既非類的成員函數也不是友元函數的普通函數


<繼承派生>
——————————————————————————————————————————————————————————————————————————————————————————
#C++代碼重用性是經過繼承這一機制來實現,提升執行時間的效果

類與類關係:has-A    uses-A    is-A
    has-A:包含關係,用以描述一個類由多個「部件類」構成。實現has-A關係用類成員表示,即一個類中的數據成員是另外一種已經定義的類
    uses-A:一個類部分地使用另外一個類。經過類之間成員函數的相互聯繫,定義友員或對象參數傳遞實現
    is-A:機制稱爲「繼承」。關係具備傳遞性,不具備對稱性。  

#基類 ——> 繼承 + 新增 = 派生類

class 派生類名:[繼承方式] 基類名{
    派生類成員聲明;
};


繼承方式:公有繼承,私有繼承,保護繼承(經常使用:公有繼承)
    公有繼承:當公有繼承時,基類的公有變成派生類的公有,保護變成派生類的保護,私有不能夠直接被派生類訪問,可經過公有和保護間接訪問!
    保護繼承:當保護繼承時,基類的公有和保護成員變成派生類的保護成員,私有成員不可直接訪問
    私有繼承:當私有繼承時,基類的公有和保護成員變成派生類的私有成員,私有成員不可直接訪問



多繼承:派生類繼承多個基類(繼承多父類特性)
#魚與熊掌兼得的作法!
  語法:class <派生類名>: <繼承方式1><基類名1> , <繼承方式2><基類名2> , ...{
            <派生類類體>;
        }



虛繼承:
1.若是一個派生類從多個基類派生,而這些基類又有一個共同的基類,則在對該基類中聲明的名字進行訪問時,可能產生二義性
2.若是在多條繼承路徑上有一個公共的基類,那麼在繼承路徑的某處匯合點,這個公共基類就會在派生類的對象中產生多個基類子對象
3.要使這個公共基類在派生類中只產生一個子對象,必須對這個基類聲明爲虛繼承,使這個基類成爲虛基類。
4.虛繼承聲明使用關鍵字virtual



繼承與構造析構:
    在子類對象構造時,須要調用父類構造函數對其繼承得來的成員進行初始化
    在子類對象析構時,須要調用父類析構函數對其繼承得來的成員進行清理

    繼承中同名成員變量處理方法:
    #同名成員變量和成員函數經過做用域分辨符進行區分
    父類和子類成員變量成員函數同名,但存儲位置不一樣,子類依然繼承父類
    經過做用域分辨符::區分
    
1.子類對象在建立時會首先調用父類的構造函數
2.父類構造函數執行結束後,執行子類的構造函數
3.當父類的構造函數有參數時,須要在子類的初始化列表中顯示調用
4.析構函數調用的前後順序與構造函數相反
5.原則:先構造父類,再構形成員變量,最後構造本身       
        先析構本身,在析構成員變量,最後析構父類


繼承中關鍵字static:
    派生類中訪問靜態成員:    類名 :: 成員
            經過對象訪問:    對象名.    成員
1.基類定義的靜態成員,將被全部派生類共享



重點:
1.一個類能夠派生自多個類,能夠從多個基類繼承數據和函數
2.is-a 關係:例如,哺乳動物是動物,狗是哺乳動物,則:狗是動物!
3.派生類能夠訪問基類中全部的非私有成員(即:public protected4.派生類繼承基類全部方法,除去:構造,拷貝,析構,友元函數和重載運算符!!



<多態>
——————————————————————————————————————————————————————————————————————————————————————————
#C++多態:意味着調用成員函數時,會根據調用函數對象的類型來執行不一樣的函數
多態: 繼承 + 虛函數重寫 + 父類指針(父類引用)指向子類對象
 











動態聯編與靜態聯編:
    聯編是指一個程序模塊、代碼之間互相關聯的過程
    
    靜態聯編:程序的匹配、鏈接在編譯階段實現,也稱爲早期匹配。重載函數使用靜態聯編
    動態聯編:程序聯編推遲到運行時進行,因此又稱爲晚期聯編(遲綁定)switch語句和if語句是動態聯編的例子

1.Cpp與C相同,是靜態編譯型語言
2.



重點:
1.多態是設計模式的基礎,多態是框架的基礎






<模板>
——————————————————————————————————————————————————————————————————————————————————————————
















<類型轉換>
——————————————————————————————————————————————————————————————————————————————————————————













<異常>
——————————————————————————————————————————————————————————————————————————————————————————












筆記
——————————————————————————————————————————————————————————————————————————————————————————
1.未初始化全局變量,在bss段(數據全爲0)
2.cpp定義全局變量兩次——int a;(bss段) int a = 1;(data段) 報錯!
3.cpp結構體定義變量-> 結構體名+變量
4.變量隨用隨定義,如for;
5.對常量取地址,編譯器會臨時開闢空間,返回臨時空間地址(看const)
6.計算機速度:cpu(寄存器)>緩存>內存>硬盤>網線
7.引用在常量區
8.函數重載就是對一個已有的函數賦予新的含義,使之實現新功能,所以,一個函數名就能夠用來表明不一樣功能的
  函數,也就是」一名多用」。
9.類表明類型,對象表明對象



拷貝構造函數代碼
new/delete 代碼
相關文章
相關標籤/搜索