<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C++知識點總結(jié)(大綱)

      C++概念

      C++基本知識

      C++基于過程

      C++基于對象

      C++面向?qū)ο?/a>

      C++概念

      C++是一門面向?qū)ο蟮木幊陶Z言,可以理解為是C語言的擴充,C語言為C++語言的子集,C++中增加了C語言中所沒有的面向?qū)ο蟮奶卣鳌C嫦驅(qū)ο笥腥筇卣鳎謩e是封裝繼承多態(tài)
      三大特征的概念:
      封裝:盡可能地隱藏對象的內(nèi)部實現(xiàn)細節(jié),控制用戶對類的修改和訪問的程度以及權(quán)限。(封裝就是隱藏)
      繼承:繼承可以使用不同的類的對象具有相同的行為;為了使用其他類的方法,我們沒有必要重新編寫這些舊方法,只要這個類(子類)繼承包含的方法的類(父類)即可。 從下往上看,繼承可以重用父類的功能;從上往下看,繼承可以擴展父類的功能。
      多態(tài):多態(tài)可以使我們以相同的方式處理不同類型的對象。我們可以使用一段代碼處理不同類型的對象,只要他們繼承/實現(xiàn)了相同的類型。這樣,我們沒有必要為每一種類型的對象撰寫相同的邏輯,極大的提高了代碼的重用。

      C++面向?qū)ο蟮募夹g(shù)實現(xiàn):
      封裝:類、訪問修飾符(public、protected、private)、
      繼承:繼承(泛化)、組合(聚合)
      多態(tài):函數(shù)重載、函數(shù)重寫、函數(shù)模板、類模板

      ======================================================================

      C++基本知識

      數(shù)據(jù)類型

      基本數(shù)據(jù)類型:整型(int)、字符型(char)、實型{單精度型(float)、雙精度型(double)}、布爾型(bool)、無值型(void)
      非基本數(shù)據(jù)類型:數(shù)組(type [])、指針(type*)、引用(type&)、類(class)、結(jié)構(gòu)體(struct)、枚舉型(enum)、聯(lián)合體(union)
      注:不同的操作系統(tǒng)中,C++的數(shù)據(jù)類型所占用的字節(jié)數(shù)是不同的,可以通過sizeof操作符來判斷在當前操作系統(tǒng)中數(shù)據(jù)類型所占用的字節(jié)數(shù)。

      文字常量

      當一個數(shù)值,例如 1,出現(xiàn)在程序中時,它被稱為文字常量 (literal constant):稱之為”文字“是因為我們只能以它的值的形式指代它,稱之為“常量”是因為它的值不能被改變。每個文字都有相應的類型,例如 0是 int 型,而3.14159是double型的文字常量,是不可尋址的(nonaddressable),盡管它的值也存儲在機器內(nèi)存的某個地方,但是我們沒有辦法訪問它們的地址。
      整數(shù)文字常量可以被寫成十進制,八進制或者十六進制的形式:
      十進制無任何標識的數(shù)字常量,如8
      八進制前綴為0,如010
      十六進制前綴為0x,如0x8
      缺省情況下,整數(shù)文字常量會被當做是int類型的有符號值。可以在文字常量的末尾添加“L”或“l(fā)”符號表示長整型,添加“U”或“u”符號表示無符號型。如:12UL、12ul、12Lu、12L等。
      缺省情況下,浮點型文字常量會被當做是double類型的值。可通過”f“、”F”后綴來表示單精度類型。同時,可通過“L”、“l(fā)”后綴來擴展精度值。(注:“f"、"F"、”L“、”l“后綴只能用在十進制中)
      字符型(char)文字常量:' '、'a'、'd'
      字符串文字類型為常量字符數(shù)組:“a”、"hello"
      布爾型(bool)文字常量:true、false
      寬字符型(wchar_t)文字常量:L'a'
      常量寬字符數(shù)組:L”hello“

      變量

      變量的概念:變量為我們提供了一個有名字的內(nèi)存存儲區(qū),可以通過程序?qū)ζ溥M行讀、寫和處理。C++中的每個符號變量都與一個特定的數(shù)據(jù)類型相關(guān)聯(lián),這個類型決定了相關(guān)內(nèi)存的大小、布局、能夠存儲在該內(nèi)存區(qū)的值的范圍以及可以應用其上的操作集 。變量與常量的區(qū)別在于,變量是可尋址的。每個變量都與兩個值相關(guān)聯(lián)——1.它的數(shù)據(jù)值,存儲在某個內(nèi)存地址中,也可被稱為右值;2.它的地址值,有時被稱為左值,我們可以認為左值是地址值。
      變量名:即變量的標識符,由數(shù)字、字符和下劃線組成,但標識符首字符只能以字符或下劃線開頭。

      const限定修飾符

      const修飾變量時,可以將變量變成常量。被const修飾的變量必須在聲明的同時初始化。如果有操作試圖修改const修飾的變量,將發(fā)生編譯錯誤。

      指針

      指針的概念:表示地址值。如果想要操作該指針地址所指向的內(nèi)存空間的內(nèi)容,需要解引用操作符“*”解除指針的引用。

      數(shù)組

      數(shù)組的概念:單一數(shù)據(jù)類型的集合。其中單個變量并未對其命名,可以通過其在數(shù)組中的位置進行訪問,這種訪問成為索引訪問或下標訪問。

      數(shù)組與指針類型的關(guān)系:數(shù)組標識符代表數(shù)組中第一個元素的地址,它的類型是數(shù)組元素類型的指針。(如ia和&ia[0]是等價的,同樣*ia和ia[0]也是等價的。)

      字符串

      C++提供了兩種字符串的表示:C 風格的字符串和標準C++引入的string 類類型(一般建議使用string型字符串)。string類型由STL提供,將在STL專題中詳解。

      引用

      引用的概念:引用(reference)有時候又稱之為別名(alias),因為它可以看作是對象的另一個名字。引用類型在定義的時候必須被初始化,因為引用類型一旦引用被定義后,就不能再指向其它對象。
      引用類型的定義形式:int a=1024;int &b=a;

      枚舉

      枚舉類型的定義形式:
      enum type_name{one,two,three};//枚舉類型定義后,type_name定義的變量類型只能為one,two,three。
      type_name type_value=one;

      聯(lián)合體

      /*聯(lián)合體定義與使用*/
      union typeName{
          char c;
          int i;
          int ii[10];
      }
      typeName t;
      

      聯(lián)合體變量的內(nèi)存大小為該聯(lián)合體類型包含的元素類型中占用字節(jié)最多的元素類大小。如上面的聯(lián)合體類型中,元素c占用一個char大小,元素i占用一個int大小,元素ii占用十個int大小,所有該聯(lián)合體類型typeName定義的變量t大小為十個int大小。

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

      /*結(jié)構(gòu)體定義與使用*/
      struct typeName{
          char c;
          int i;
          int ii[10];
      }
      typeName t;
      

      結(jié)構(gòu)體的大小為結(jié)構(gòu)體類型內(nèi)包含所有元素的類型大小之和。

      復數(shù)類型

      復數(shù)類是C++標準庫的一部分,包含在頭文件#include<complex>中。
      復數(shù)的概念:復數(shù)有兩部分組成:實數(shù)部分和虛數(shù)部分。其表現(xiàn)形式如:3+4i
      復數(shù)對象的定義:
      complex c1(0,7);//表示0+7i,純虛數(shù)
      complex c2(3);//表示3+0i,虛數(shù)部分缺省為0
      complex c3;//表示0+0i,實數(shù)部分和虛數(shù)部分都缺省為0
      complex c4(c1);//用另一個虛數(shù)來初始化一個新的虛數(shù)對象

      pair類型

      pair類型是C++標準庫的一部分,包含在頭文件#include中。
      pair類型的概念:
      pair對象的定義:
      pair<string,string> p1("name1","name2");
      可以用成員訪問符號“.”來訪問pair單個成員的內(nèi)容,如:p1.first;p1.second;

      容器類型

      容器的定義:在數(shù)據(jù)存儲上,有一種對象類型,它可以持有其它對象或指向其它對像的指針,這種對象類型就叫做容器。樸素地看,容器就是存儲其它對象的對象。
      C++的容器由C++標準模板庫(STL)提供,STL 對定義的通用容器分三類:順序性容器、關(guān)聯(lián)式容器和容器適配器。
      順序性容器:順序性容器是一種各元素之間有順序關(guān)系的線性表,是一種線性結(jié)構(gòu)的可序群集。順序性容器中的每個元素均有固定的位置,除非用刪除或插入的操作改變這個位置。這個位置和元素本身無關(guān),而和操作的時間和地點有關(guān),順序性容器不會根據(jù)元素的特點排序而是直接保存了元素操作時的邏輯順序。(vector、deque、list
      關(guān)聯(lián)式容器:關(guān)聯(lián)式容器和順序性容器不一樣,關(guān)聯(lián)式容器是非線性的樹結(jié)構(gòu),更準確的說是二叉樹結(jié)構(gòu)。各元素之間沒有嚴格的物理上的順序關(guān)系,也就是說元素在容器中并沒有保存元素置 入容器時的邏輯順序。但是關(guān)聯(lián)式容器提供了另一種根據(jù)元素特點排序的功能,這樣迭代器就能根據(jù)元素的特點“順序地”獲取元素。(set/multiset、map/multimap)
      容器適配器:簡單的理解容器適配器,其就是將不適用的序列式容器(包括 vector、deque 和 list)變得適用。(stack、queue、priority_queue
      關(guān)于STL容器的總體與詳細內(nèi)容,將在《C++標準模板庫(STL)詳解》中介紹。

      typedef修飾符

      typedef的定義形式:typedef 數(shù)據(jù)類型 標識符;//如typedef int my_int;
      typedef并未引入新類型,只是為數(shù)據(jù)類型引入了一個助記符。(與引用相似的地方在于,引用相當于為變量起別名,而typedef相當于為數(shù)據(jù)類型起別名。)

      volatile限定修飾符

      volatile修飾符與const的相似之處在于,它們都是附加修飾符。由于編譯器會在處理源代碼時對代碼做一些優(yōu)化,而有時候?qū)τ谟行┲颠@些優(yōu)化將導致出錯。volatile的主要作用在于提示編譯器,不要武斷地對被volatile修飾的值進行優(yōu)化。

      表達式

      表達式由一個或多個操作數(shù)和N(N>=0)個操作符構(gòu)成。

      復數(shù)操作

      條件操作符

      操作形式:判斷表達式?判斷為真時執(zhí)行此表達式:判斷為假時執(zhí)行此表達式;

      sizeof操作符

      作用:返回一個對象或類型名的字節(jié)長度,其返回值為size_t類型。
      三種操作方式:

      1. sizeof(type_name);//如sizeof(類型名)
      2. sizeof(object);//如sizeof(對象名)
      3. sizeof object;//如sizeof 對象名

      new和delete操作符

      系統(tǒng)為每個程序都提供了一個在程序執(zhí)行時可用的內(nèi)存池,這個可用內(nèi)存池被稱為程序的空閑存儲區(qū)(free store)或堆(heap)運行時刻的內(nèi)存分配被稱為動態(tài)內(nèi)存分配(dynamic memory allocation)。動態(tài)內(nèi)存分配由new表達式應用在一個類型指示符(specifier)上來完成。類型指示符可以是內(nèi)置類型或用戶定義類型。
      如:int *a=new int;delete a;或者int *a=new int[n];delete[] a;

      位操作符

      操作符 功能 用法
      ~ 按位非 ~expr
      << 左移 expr1 << expr2
      >> 右移 expr1 >> expr2
      & 按位與 expr1 & expr2
      ^ 按位異或 expr1 ^ expr2
      ` ` 按位或
      &= 按位與賦值 expr1 &= expr2
      ^= 按位異或賦值 expr1 ^= expr2
      ` `= 按位或賦值
      ? 00000101
      ^ 00000110
      ---------
      ? 00000011

      bitset類型

      運算符優(yōu)先級

      類型轉(zhuǎn)換

      語法

      聲明語句

      ======================================================================

      C++基于過程

      域和生命周期

      C++作用域的關(guān)鍵詞:extern
      C++生命周期的關(guān)鍵詞:static
      C++支持三種形式的域:局部域名字空間域類域
      全局域:全局對象和非inline全局函數(shù)只能定義一次,inline函數(shù)可以被定義多次。
      函數(shù)聲明:函數(shù)聲明(declaration)指定了該函數(shù)的名字以及函數(shù)的返回類型和參數(shù)表。
      函數(shù)定義:函數(shù)定義(definition)包含了函數(shù)聲明部分,同時還為函數(shù)提供了函數(shù)體。
      extern關(guān)鍵詞:修飾符extern用在變量或者函數(shù)的聲明前,用來說明“此變量/函數(shù)是在別處定義的,要在此處引用”。extern聲明不是定義,即不分配存儲空間。extern “c”表示C語言代碼。
      在局部域中的變量聲明引入了局部對象。有三種局部對象:自動對象、寄存器對象(register關(guān)鍵詞)以及局部靜態(tài)對象(static關(guān)鍵詞)。

      函數(shù)

      概念:函數(shù)由返回值類型函數(shù)名參數(shù)列表函數(shù)體構(gòu)成。
      函數(shù)形式:返回值類型 函數(shù)名(參數(shù)列表){函數(shù)體}
      函數(shù)原型:函數(shù)原型由返回值類型、函數(shù)名和參數(shù)列表構(gòu)成。

      函數(shù)傳參

      指針參數(shù)和引用參數(shù)的區(qū)別:指針可以指向任何對象,也可以不指向任何對象,在知道指針指向一個有效對象之前不能輕易的對指針進行解引用;引用則必須明確的指向一個對象,且一旦指向之后就不可以更改,否則就會報錯。
      例如:

      void f(int* a,int& b){
          if(!a)std::cout<<*a<<std::endl;//當參數(shù)為指針時,必須先判斷該指針是否指向一個有效對象,再使用。
          std::cout<<b<<std::endl;//當參數(shù)為引用時,可以直接使用
      }
      int main(){
          int i=0;
          f(&i,i);//正確
          f(nullptr,i);//正確
          f(nullptr,0);//錯誤表示!引用參數(shù)必須為一個對象,不能是常量
          return 0;
      }
      

      所以,如果一個參數(shù)可能在函數(shù)中指向不同的對象,或者不指向任何對象,則必須使用參數(shù)指針。當一個參數(shù)在函數(shù)中只指向一個確定的對象,則使用引用參數(shù)。

      重載函數(shù)

      概念:在同一作用域內(nèi),一組函數(shù)的函數(shù)名相同參數(shù)列表不同(參數(shù)個數(shù)不同/參數(shù)類型不同),返回值可同可不同。
      函數(shù)重載:
      1、具有相同的名稱,執(zhí)行基本相同的操作,但是使用不同的參數(shù)列表。
      2、函數(shù)的多態(tài)性。
      3、編譯器通過調(diào)用時參數(shù)的個數(shù)和類型確定調(diào)用重載函數(shù)的哪個定義。
      4、只有對不同的數(shù)據(jù)集完成基本相同任務的函數(shù)才應重載。
      函數(shù)重載的優(yōu)點:
      1、減少了函數(shù)名的數(shù)量
      2、增加了代碼的可讀性,有助于理解和調(diào)試代碼
      3、易于維護代碼
      函數(shù)重載是一種靜態(tài)多態(tài)。(關(guān)于多態(tài)的詳細全面的內(nèi)容,將在《C++三大特性(封裝、繼承和多態(tài))及其技術(shù)實現(xiàn)詳解》一文中詳解)
      C++函數(shù)重載的原理:
      函數(shù)重載解析:把函數(shù)調(diào)用與重載函數(shù)集合中的一個函數(shù)相關(guān)聯(lián)的過程 。
      編譯器在編譯.cpp文件中當前使用的作用域里的同名函數(shù)時,根據(jù)函數(shù)形參的類型順序會對函數(shù)進行重命名(不同的編譯器在編譯時對函數(shù)的重命名標準不一樣)但是總的來說,他們都把文件中的同一個函數(shù)名進行了重命名;

      • 在vs編譯器中:
        根據(jù)返回值類型(不起決定性作用)+形參類型和順序(起決定性作用)的規(guī)則重命名并記錄在map文件中。
      • 在linux g++ 編譯器中:
        根據(jù)函數(shù)名字的字符數(shù)+形參類型和順序的規(guī)則重命名記錄在符號表中;從而產(chǎn)生不同的函數(shù)名,當外面的函數(shù)被調(diào)用時,便是根據(jù)這個記錄的結(jié)果去尋找符合要求的函數(shù)名,進行調(diào)用;
        為什么C語言沒有函數(shù)重載機制?
        編譯器在編譯.c文件時,只會給函數(shù)進行簡單的重命名;具體的方法是給函數(shù)名之前加上”_”;所以加入兩個函數(shù)名相同的函數(shù)在編譯之后的函數(shù)名也照樣相同;調(diào)用者會因為不知道到底調(diào)用那個而出錯;

      函數(shù)模板

      關(guān)鍵字:template、class、typename
      例:

      /*a.h*/
      template <class Type,int size>
      Type functionName(Type (&type_name)[size]){}//當調(diào)用此函數(shù)時,需要在Type傳入數(shù)據(jù)類型,size位置傳入int型常量
      
      /*b.c*/
      #include "a.h"
      int main(){
          int ia[5]={1,2,3,4,5};
          /*函數(shù)模板實例化*/
          int i=functionName(ia);//該模板函數(shù)的Type為int,size為5.
          return 0;
      }
      

      模板編譯模式分為:分離編譯模式、包含編譯模式
      包含編譯模式:函數(shù)模板的聲明和定義都放在頭文件中。
      分離編譯模式:函數(shù)模板的聲明放在頭文件中,定義放在源文件中。
      顯式實例化聲明:
      如:

      /*函數(shù)模板*/
      template <class T>
      T f(T t,int i);
      
      /*顯式實例化聲明*/
      template int f(int t,int i);
      

      模板顯式特化:
      定義:

      異常處理

      關(guān)鍵字:try、catch、throw
      概念:異常是程序可能檢測到的,運行時刻不正常的情況,如除0、數(shù)組訪問越界或存儲內(nèi)存耗盡等。

      泛型算法

      ======================================================================

      C++基于對象

      類定義和訪問權(quán)限

      類聲明
      類聲明的形式:class 類名;
      例如:class Vector;
      聲明一個Vector類類型,但是由于未定義,不知道該類類型的大小,編譯器不知道為該類類型的對象預留多少空間,所以也無法定義該類類型對象。但是,可以聲明一個指向該類類型的指針或引用,因為指針和引用的內(nèi)存大小與所指向的對象大小無關(guān)。
      類定義
      類定義包含兩部分:類頭,由關(guān)鍵字class和類名構(gòu)成;類體,花括號內(nèi)內(nèi)容。
      類體定義了類成員表,類成員表包括數(shù)據(jù)成員成員函數(shù)
      成員訪問
      信息隱藏:防止程序的函數(shù)直接訪問類的內(nèi)部信息而提供的一種機制。通過訪問限定符(public、protected、private)來實現(xiàn)。
      公有成員(public):在程序的任何地方都可以被訪問。
      私有成員(private):只能被成員函數(shù)和類的友元訪問。
      被保護成員(protected):派生類可訪問,非派生類不可訪問。

      友元訪問

      在某些情況下,允許某個函數(shù)而不是整個程序可以訪問類的私有成員,這樣做會比較方便,友元機制允許一個類授權(quán)其他的函數(shù)訪問它的非公有成員。友元聲明以關(guān)鍵字 friend 開頭,它只能出現(xiàn)在類的聲明中。
      友元可分為:友元類友元函數(shù)
      詳細內(nèi)容見友元訪問在操作符重載的應用

      類的初始化、賦值和析構(gòu)

      類的構(gòu)造函數(shù)

      關(guān)鍵詞:explicit、inline、const、volatile
      構(gòu)造函數(shù)概念:類的構(gòu)造函數(shù)與類名同名,且無返回值類型。C++可以有多個構(gòu)造函數(shù),唯一的要求是這些函數(shù)參數(shù)列表不能相同。一般構(gòu)造函數(shù)用來初始化類中的數(shù)據(jù)成員,對于有些需要傳參的構(gòu)造函數(shù),當參數(shù)經(jīng)常使用默認值時,可以使用缺省參數(shù)。
      例如:

      /*例1:構(gòu)造函數(shù)使用缺省參數(shù)的類*/
      class Account{
      public:
          //缺省構(gòu)造函數(shù)
          Account(){}
          Account(int i,int j=111,int x=111):i_(i),j_(j),x_(x){std::cout<<"使用缺省實參的構(gòu)造函數(shù)"<<std::endl;}
      private:
          int i_;
          int j_;
          int x_;
      };
      
      /*例2:使用普通構(gòu)造函數(shù)的類*/
      class Account{
      public:
          //缺省構(gòu)造參數(shù)
          Account(){}
          Account(int i,int j,int x):i_(i),j_(j),x_(x){std::cout<<"普通構(gòu)造函數(shù)"<<std::endl;}
          Account(int i,int j):i_(i),j_(j){
              x_=111;
          }
          Account(int i):i_(i){
              j_=111;
              x_=111;
          }
      private:
          int i_;
          int j_;
          int x_;
      };
      

      例1和例2中的類的構(gòu)造函數(shù)結(jié)果是等價的,都可以傳入一個參數(shù),兩個參數(shù),或者三個參數(shù)。但是從效果上來看,例1中利用缺省參數(shù)的構(gòu)造函數(shù)更好,節(jié)省代碼量,也利于理解。

      構(gòu)造函數(shù)重點:缺省構(gòu)造函數(shù)限制對象創(chuàng)建拷貝構(gòu)造函數(shù)
      1、缺省構(gòu)造函數(shù):沒有參數(shù),或參數(shù)都是默認值。一個類最多有一個缺省構(gòu)造函數(shù)。
      2、限制對象創(chuàng)建:將某些構(gòu)造函數(shù)聲明為private型,從而限制通過某些構(gòu)造函數(shù)創(chuàng)建對象。
      3、拷貝構(gòu)造函數(shù):用一個類對象初始化該類的另一個對象。

      拷貝構(gòu)造函數(shù):
      拷貝構(gòu)造函數(shù)就是用一個類對象初始化該類的另一個對象,但是拷貝構(gòu)造函數(shù)的參數(shù)必須是同一個類的引用對象
      一個對象的拷貝構(gòu)造函數(shù)可以訪問被拷貝的對象的私有成員,例如:

      class Demo{
      public:
          Demo(){}
          Demo(const Demo& demo):i(demo.i){"std::cout<<拷貝構(gòu)造函數(shù)<<std::endl;"}//拷貝構(gòu)造函數(shù),參數(shù)必須是Demo&類型。
      private:
          int i;
      }
      

      類的數(shù)據(jù)成員初始化

      類中的數(shù)據(jù)成員能否在定義類的時候就初始化?

      存在問題,仍未解決~

      class Demo{
      public:
          Demo(){}
      private:
          int i=0;//此處在定義類的時候初始化
      }
      

      答案是不能在此處初始化。原因在于:1、類的定義實際上相當于類型的聲明,里面的數(shù)據(jù)成員都是聲明,類型聲明并沒有分配內(nèi)存空間,所以無法存放該類型;2、假如類是抽象類,那么在類中特征初始化將破壞類的抽象性。

      • const成員:也就是常量成員,它們在聲明時就要初始化,因為它們?yōu)槌A砍蓡T,一旦定義,就不能修改
      • 引用成員&:引用代表的就是被引用者自身,是變量的別名,所以引用類型變量一旦初始化,它們也不能修改
      • const、引用成員必須在類的構(gòu)造函數(shù)中的初始化列表中初始化,不能在構(gòu)造函數(shù)的函數(shù)體中進行賦值
      • static成員:靜態(tài)成員,它不像其他成員,static沒有隱藏的this指針,所以static成員是屬于整個類的,不是某個對象的,靜態(tài)成員的初始化要在類外初始化,在類外初始化時需要隱藏static關(guān)鍵字,只有整形靜態(tài)常量可以在類內(nèi)初始化
      • 整型靜態(tài)常量:static const int 類型,這種數(shù)據(jù)類型可以在類內(nèi)初始化
      class A{
      public:
          const int a; // 常量成員,需要在構(gòu)造函數(shù)的初始化列表中賦值初始化
          int& b; // 引用成員,也是構(gòu)造函數(shù)的初始化列表賦值
          static int c; // 靜態(tài)成員,要在類外初始化
          static const int d = 0; // 靜態(tài)整形,可以在類內(nèi)初始化
          static int f;
          static const double e; // 只能在類外初始化
          A(int a, int& b ):a(a), b(b){}
      }
      // 需要在類外初始化的成員變量,隱藏static關(guān)鍵字
          const double A::e = 1.0;
          const int A::f = 1; // 也可在類外初始化
      

      類的析構(gòu)函數(shù)

      釋放在該類內(nèi)申請的動態(tài)資源。

      重載操作符和用戶定義的轉(zhuǎn)換

      操作符重載

      形式:返回值 operator操作符(參數(shù)列表){函數(shù)體}
      注意:重載操作符的函數(shù)參數(shù)列表中必須至少有一個操作數(shù)為類類型。
      例如:

      /*將<<操作符重載為用以計算兩個int類型值之和,這種是錯誤的,因為兩個重載操作符的函數(shù)兩個參數(shù)都是非類的數(shù)據(jù)類型*/
      int operator<<(int i,int j){
          return i+j;
      }
      int main(){
          int i=111,j=222;
          int sum=i<<j;//相當于int sum=operator<<(i,j);
          return 0;
      }
      
      /*將<<操作符重載為用以計算int變量和A類對象數(shù)據(jù)成員j的和,并返回int類型結(jié)果,這種是正確的,因為該操作符重載函數(shù)有一個參數(shù)為類類型*/
      class A{
      public:
          A(int _j):j(_j){}
          int j;
      };
      int operator<<(int i,A j){
          return i+j.j;
      }
      int main(){
          int i=111;
          A a(222);
          int sum=i<<a;//相當于int sum=operator<<(i,a);
          cout<<sum<<endl;
          return 0;
      }
      

      友元訪問在操作符重載的應用

      友元訪問分為:
      1、友元類訪問:將一個類聲明為另一個類的友元類。如:

      class Demo1{}
      class Demo{
          friend class Demo1;
      public:/*……*/
      private:/*……*/
      };
      

      2、友元函數(shù)訪問:將一個函數(shù)聲明為另一個類的友元函數(shù)。如:

      void f(){}
      class Demo{
          friend void f();
      public:/*……*/
      private:/*……*/
      };
      

      操作符重載分為幾種不同情況,對應幾種不同的操作符重載函數(shù),需要不同的編程技巧:
      情況一:重載操作符函數(shù)為全局函數(shù),形式上是兩個操作數(shù),函數(shù)參數(shù)也是兩個操作數(shù),且兩個操作符可以為任意變量類型。
      在這種情況下,當操作數(shù)有類類型時,在函數(shù)內(nèi)如果想要直接訪問類內(nèi)成員需要設(shè)置為該類的友元函數(shù)(當然也可以不訪問)。例如:

      /*
      重載+操作符,左邊為基本數(shù)據(jù)類型,右邊為類類型,返回值為類類型。
      形式:類類型=基本數(shù)據(jù)類型+類類型;
      */
      class Demo{
      public:
          friend Demo operator+(int i,Demo& j);//聲明操作符重載函數(shù)為類Demo的友元函數(shù)
          Demo(int _i):i(_i){}
          int getValue(){return i;}
      private:
          int i;
      };
      /*操作符重載函數(shù)*/
      Demo operator+(int i,Demo& j){
          Demo sum(i+j.i);//其實也未必需要將操作符重載函數(shù)設(shè)置為Demo類的友元函數(shù),因為類的數(shù)據(jù)成員可以間接訪問,可以直接將sum(i+j.i)改為sum(i+j.getValue())即可。
          return sum;
      }
      
      int main(){
          int d1=111;
          Demo d2(222);
          Demo d3=d1+d2;//此時相當于調(diào)用了全局函數(shù)operator+(d1,d2),相當于將形式上兩個操作數(shù)作為兩個參數(shù)傳入了全局函數(shù)中。
          cout<<d3.getValue()<<endl;
          return 0;
      }
      

      情況二:重載操作符函數(shù)為成員函數(shù),形式上是兩個操作數(shù),函數(shù)參數(shù)是一個操作數(shù),但是形式上的左操作數(shù)必須是重載操作符函數(shù)的類,右操作數(shù)可以為任意類型。

      class Demo{
      public:
          Demo operator+(int i){//重載操作符函數(shù)為成員函數(shù)
              Demo sum(this->i+i);
              return sum;
          }
          Demo(int _i):i(_i){}
          int getValue(){return i;}
      private:
          int i;
      };
      
      int main(){
          int d1=111;
          Demo d2(222);
          Demo d3=d2+d1;/*相當于調(diào)用了Demo類的成員函數(shù)d2.operator+(d1),所以不能寫成d1+d2,否則會編譯錯誤。因為d1是int類型,而重載操作符函數(shù)是Demo的類成員函數(shù) 。形式上兩個操作數(shù),實際上是一個操作數(shù)對象調(diào)用了成員函數(shù),并將另一個操作數(shù)作為參數(shù)傳入。如果想要d1+d2合法,這時需要些一個全局函數(shù)來重載操作符+*/
          return 0;
      }
      

      類模板

      類模板的定義與實例化

      模板類的定義形式:

      template<class T1,typename T2,int size>
      class Demo{
      public:
          void prin(){
              for(int i=0;i<size;i++)std::cout<<t1[i]<<std::endl;
              for(int i=0;i<size;i++)std::cout<<t2[i]<<std::endl;
          }
      private:
          T1 t1[size];
          T2 t2[size];
      }
      

      模板類型參數(shù):用關(guān)鍵詞class或typename聲明。當實例化時會用數(shù)據(jù)類型標識符替換,例如T1替換成int。
      模板非類型參數(shù):用數(shù)據(jù)類型標識符聲明。當實例化時會用該數(shù)據(jù)類型的常量替換,例如size替換成int類型的常量10。
      總結(jié):模板類型參數(shù)相當于以數(shù)據(jù)類型為參數(shù),通俗的說就是把數(shù)據(jù)類型當成類模板的變量;而模板非類型參數(shù)相當于以數(shù)據(jù)類型的常量表達式為參數(shù),通俗來講就是把常量表達式的計算結(jié)果(常量表達式計算結(jié)果為常量)當成類模板的變量
      將模板類型參數(shù)與非類型參數(shù)替換成具體的數(shù)據(jù)類型與數(shù)據(jù)類型常量的過程,稱為模板實例化
      類模板的參數(shù)可以有缺省實參,這對類型參數(shù)和非類型參數(shù)都一樣。就像函數(shù)參數(shù)的缺省,模板參數(shù)的缺省是一個類型或一個值。如下示例:

      template<class T1,class T2=string,int size=1024>//T1缺省為string類型,size缺省為計算結(jié)果為int類型的常量表達式1024
      class Demo{
      public:
          Demo(T1 _t1,T2 _t2):t1(_t1),t2(_t2){}
          void printValue(){
              std::cout<<"t1="<<t1<<std::endl;
              std::cout<<"t2="<<t2<<std::endl;
              std::cout<<"size="<<size<<std::endl;
          }
      private:
          T1 t1;
          T2 t2;
      };
      
      int main(){
          int i=1234;
          Demo<string> demo("sss","mmm",i);//此處可以傳入變量i,是因為此處非類型參數(shù)以常量表達式的計算結(jié)果為參數(shù)。
          demo.printValue();
          return 0;
      }
      
      

      注意:在參數(shù)列表中,缺省參數(shù)右邊必須都是缺省參數(shù),否則編譯器將報錯。
      從通用的類模板定義生成類的過程被稱為模板實例化

      在模板實參的類型和非類型模板參數(shù)的類型之間允許進行一些轉(zhuǎn)換,能被允許的轉(zhuǎn)換集
      是“函數(shù)實參上被允許的轉(zhuǎn)換”的子集:
      1、左值轉(zhuǎn)換,包括從左值到右值的轉(zhuǎn)換、從數(shù)組到指針的轉(zhuǎn)換,以及從函數(shù)到指針的轉(zhuǎn)換。例如:

      template <int *ptr> class Demo{};
      int array[10];
      Demo<array> demo;//從數(shù)組到指針的轉(zhuǎn)換
      

      2、限定修飾符轉(zhuǎn)換。例如:

      template <const int* ptr> class Demo{};
      int i;
      Demo<&i> demo;//從int*類型到const int*類型的轉(zhuǎn)換 
      

      3、提升。例如:

      template <int i> class Demo{};
      const short int ii;
      Demo<ii> demo;//從short到int類型的提升
      

      4、數(shù)值轉(zhuǎn)換。例如:

      template <unsigned int size> Demo{};
      Demo<1024> demo;//從int類型到unsigned int類型
      

      類模板中的友元聲明

      有三種友元聲明可以出現(xiàn)在類模板中:
      1、非模板友元類或友元函數(shù)。友元類和友元函數(shù)都是非模板的。
      例如:

      class Foo {//非模板類
          void bar();//非模板類的非模板成員函數(shù)
      };
      void foo();//非模板函數(shù)
      template <class T>
      class QueueItem {
          friend class foobar;//非模板友元類
          friend void foo();//非模板友元函數(shù)
          friend void Foo::bar();//非模板友元類的非模板成員函數(shù)
          // ...
      };
      
      

      2、綁定的友元類模板或函數(shù)模板。友元類和友元函數(shù)都是模板的,但是已經(jīng)與實例化模板函數(shù)/類綁定,相當于該友元只能是某種實例化的模板函數(shù)/類。

      template <class Type>
      class foobar{ ... };//類模板
      
      template <class Type>
      void foo( QueueItem<Type> );//函數(shù)模板
      
      template <class Type>
      class Queue {
          void bar();//類模板的成員函數(shù)模板
      // ...
      };
      
      template <class Type>
      class QueueItem {
      friend class foobar<Type>;//綁定的模板友元類
      friend void foo<Type>( QueueItem<Type> );//綁定的模板友元函數(shù)
      friend void Queue<Type>::bar();//綁定的模板類友元成員函數(shù)
      // ...
      };
      

      3、非綁定的友元類模板或函數(shù)模板

      template <class Type>
      class QueueItem {
          template <class T>
          friend class foobar;//非綁定的模板友元類
          
          template <class T>
          friend void foo( QueueItem<T> );//非綁定的模板友元函數(shù)
          
          template <class T>
          friend void Queue<T>::bar();//非綁定的模板類友元成員函數(shù)
          // ...
      };
      

      注意:友元的目的是為了訪問友元聲明時所在類的私有數(shù)據(jù)成員,不改變該類的數(shù)據(jù)成員與成員函數(shù)的數(shù)量或其它。

      類模板的靜態(tài)數(shù)據(jù)成員

      ======================================================================

      C++面向?qū)ο?/h2>

      類繼承和子類型

      基類和派生類的定義

      基類必須被定義才能作為基類。例如:

      class Parent;
      class Child:public Parent{/*……*/};//錯誤,基類Parent必須被定義,只有聲明是無效的
      

      前向聲明不能包含派生類的派生表。例如:

      class Parent{};
      class Child:public Parent;//錯誤,Child類為前向聲明,還未定義,前向聲明不能包含派生類的派生表
      

      派生類的前向聲明正確的方法是:

      class Parent{};
      class Child;
      

      基類的構(gòu)造:
      1、基類構(gòu)造函數(shù)。如果有多個基類,則構(gòu)造函數(shù)的調(diào)用順序是某類在類派生表中出現(xiàn)的順序,而不是它們在成員初始化表中的順序。
      2、成員類對象構(gòu)造函數(shù)。如果有多個成員類對象,則構(gòu)造函數(shù)的調(diào)用順序是對象在類中,被聲明的順序,而不是它們出現(xiàn)在成員初始化表中的順序。
      3、派生類構(gòu)造函數(shù)。作為一般規(guī)則,派生類構(gòu)造函數(shù)應該不能直接向一個基類數(shù)據(jù)成員賦值,而是把值傳遞,否則基類和派生類會變成“緊耦合”,當修改基類數(shù)據(jù)成員時會影響派生類。
      基類與派生類構(gòu)造函數(shù)

      class Parent{
      public:
          Parent(int i):_i(i){}
      private:
          int _i;
      };
      
      class Child:public Parent{
      public:
          Child(int i,int j):Parent(i),_j(j){}
      private:
          int _j;
      };
      

      還為了解的點:遲緩型錯誤檢測

      繼承關(guān)系中類的構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用順序

      構(gòu)造函數(shù)分為:父類的構(gòu)造函數(shù),父類數(shù)據(jù)成員的構(gòu)造函數(shù),子類的構(gòu)造函數(shù),子類數(shù)據(jù)成員的構(gòu)造函數(shù)。
      構(gòu)造函數(shù)的調(diào)用順序為
      1、父類數(shù)據(jù)成員的構(gòu)造函數(shù);
      2、父類的構(gòu)造函數(shù);
      3、子類數(shù)據(jù)成員的構(gòu)造函數(shù);
      4、子類的構(gòu)造函數(shù)。
      析構(gòu)函數(shù)的調(diào)用順序完全相反。
      另外,當父類或子類擁有多個數(shù)據(jù)成員時,數(shù)據(jù)成員構(gòu)造函數(shù)的調(diào)用順序與父類或子類構(gòu)造函數(shù)的成員初始化表的順序無關(guān),而與類中定義該數(shù)據(jù)成員的順序有關(guān)。
      例如:

      class Demo{
      public:
          Demo(string s):_s(s){cout<<"Demo構(gòu)造函數(shù):"<<s<<endl;}
          ~Demo(){cout<<"Demo析構(gòu)函數(shù)"<<_s<<endl;}
      private:
          string _s;
      };
      
      class Parent{
      public:
          Parent(int i):_i(i),d_parent2("d_parent2"),d_parent1("d_parent1"){cout<<"Parent構(gòu)造函數(shù)"<<endl;}
          ~Parent(){cout<<"Parenet析構(gòu)函數(shù)"<<endl;}
      private:
          int _i;
          Demo d_parent1;
          Demo d_parent2;
      };
      
      class Child:public Parent{
      public:
          Child(int i,int j):d_child2("d_child2"),Parent(i),_j(j),d_child1("d_child1"){cout<<"Child構(gòu)造函數(shù)"<<endl;}
          ~Child(){cout<<"Child析構(gòu)函數(shù)"<<endl;}
      private:
          int _j;
          Demo d_child1;
          Demo d_child2;
      };
      
      int main(){
          Child c(1,2);
          return 0;
      }
      

      運行結(jié)果是:

      Demo構(gòu)造函數(shù):d_parent1
      Demo構(gòu)造函數(shù):d_parent2
      Parent構(gòu)造函數(shù)
      Demo構(gòu)造函數(shù):d_child1
      Demo構(gòu)造函數(shù):d_child2
      Child構(gòu)造函數(shù)
      Child析構(gòu)函數(shù)
      Demo析構(gòu)函數(shù)d_child2
      Demo析構(gòu)函數(shù)d_child1
      Parenet析構(gòu)函數(shù)
      Demo析構(gòu)函數(shù)d_parent2
      Demo析構(gòu)函數(shù)d_parent1
      
      Process returned 0 (0x0)   execution time : 0.742 s
      Press any key to continue.
      

      基類與派生類的虛擬函數(shù)

      缺省情況下,類的成員函數(shù)是非虛擬的(nonvirtual)。當一個成員函數(shù)為非虛擬的時候,通過一個類對象(指針或引用)而被調(diào)用的該成員函數(shù),就是該類對象的靜態(tài)類型中定義的成員函數(shù)。例如:

      class Parent{
      public:
          void demo(){cout<<"Parent"<<endl;}
      };
      class Child:public Parent{
      public:
          void demo(){cout<<"demo"<<endl;}
      };
      
      int main(){
          Parent *p=new Child;//定義p的靜態(tài)類型為Parent類型,而分配內(nèi)存的動態(tài)類型為Child
          p->demo();//通過類對象的指針調(diào)用該函數(shù)
          Parent &cp=*p;
          cp.demo();//通過類對象的引用調(diào)用該函數(shù)
          return 0;
      }
      

      此時的執(zhí)行輸出結(jié)果為:
      Parent
      Parent

      純虛函數(shù):沒有函數(shù)體的函數(shù)聲明=0。例如:virtual void demo()=0;

      虛函數(shù)可以通過動態(tài)聯(lián)編動態(tài)調(diào)用,也可以靜態(tài)調(diào)用,例如:

      class Parent{
      public:
          virtual void demo(){cout<<"Parent"<<endl;}
      };
      class Child:public Parent{
      public:
          void demo(){cout<<"demo"<<endl;}
      };
      
      int main(){
          Parent *p=new Child;
          p->Parent::demo();//虛擬函數(shù)的靜態(tài)調(diào)用,在編譯時刻解析,調(diào)用的類型為定義指針的類型
          p->demo();//虛擬函數(shù)的動態(tài)調(diào)用,在運行時刻動態(tài)聯(lián)編,調(diào)用的類型為指針所指向地址的對象類型
          return 0;
      }
      

      虛析構(gòu)函數(shù)

      當我們通過基類的指針來銷毀對象,如果析構(gòu)函數(shù)不為虛的話,就不能正確識別對象類型,從而不能正確銷毀對象。
      例如:

      /*基類的析構(gòu)函數(shù)沒有被聲明為虛函數(shù)時*/
      class Parent{
      public:
          Parent(){cout<<"Parent構(gòu)造函數(shù)"<<endl;}
          ~Parent(){cout<<"Parent析構(gòu)函數(shù)"<<endl;}
      };
      class Child:public Parent{
      public:
          Child(){cout<<"Child構(gòu)造函數(shù)"<<endl;}
          ~Child(){cout<<"Child析構(gòu)函數(shù)"<<endl;}
      };
      
      int main(){
          Parent* p=new Child;
          delete p;//通過基類的指針來銷毀對象,此時父類的析構(gòu)函數(shù)不是虛函數(shù)
          return 0;
      }
      

      運行結(jié)果為:

      Parent構(gòu)造函數(shù)
      Child構(gòu)造函數(shù)
      Parent析構(gòu)函數(shù)
      Process returned 0 (0x0)   execution time : 0.647 s
      Press any key to continue.
      
      /*基類的析構(gòu)函數(shù)被聲明為虛函數(shù)時*/
      class Parent{
      public:
          Parent(){cout<<"Parent構(gòu)造函數(shù)"<<endl;}
          virtual ~Parent(){cout<<"Parent析構(gòu)函數(shù)"<<endl;}
      };
      class Child:public Parent{
      public:
          Child(){cout<<"Child構(gòu)造函數(shù)"<<endl;}
          ~Child(){cout<<"Child析構(gòu)函數(shù)"<<endl;}
      };
      
      int main(){
          Parent* p=new Child;
          delete p;//通過基類的指針來銷毀對象,此時父類的析構(gòu)函數(shù)是虛函數(shù)
          return 0;
      }
      

      運行結(jié)果為:

      Parent構(gòu)造函數(shù)
      Child構(gòu)造函數(shù)
      Child析構(gòu)函數(shù)
      Parent析構(gòu)函數(shù)
      Process returned 0 (0x0)   execution time : 0.485 s
      Press any key to continue.
      

      可以得出結(jié)論,將基類的析構(gòu)函數(shù)聲明為虛函數(shù)常常是必要的,否則銷毀對象時可能會導致析構(gòu)不完整。

      未完待續(xù)……

      posted @ 2021-04-02 13:45  一只小菜菜鳥  閱讀(4008)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 亚洲真人无码永久在线| 国产精品亚洲综合久久小说| 婷婷99视频精品全部在线观看 | 99久久精品视香蕉蕉| 国产性色av免费观看| 无码h片在线观看网站| 麻豆精品一区二区三区蜜臀| 国产极品粉嫩福利姬萌白酱| 国产精品普通话国语对白露脸| 亚洲精品www久久久久久| 50岁熟妇的呻吟声对白| 鹰潭市| 亚洲欧美在线观看品| 亚洲中文字幕一二区日韩| 夜夜添狠狠添高潮出水| 亚洲综合色婷婷中文字幕| 免费人成在线观看品爱网| 亚洲更新最快无码视频| 久久综合97丁香色香蕉| 野花韩国高清电影| 久久三级国内外久久三级| 四虎在线中文字幕一区| 国产大学生自拍三级视频| 毛片亚洲AV无码精品国产午夜| 国产初高中生粉嫩无套第一次| 免费国产一区二区不卡| 亚洲精品熟女国产| 亚洲成aⅴ人在线电影| 国产精品一区久久人人爽| 亚洲AV永久中文无码精品综合| 女人与牲口性恔配视频免费| 亚洲国产精品日韩av专区| 亚洲精品麻豆一二三区| 久久99久国产精品66| 国产美女被遭强高潮免费一视频| 国产午夜福利短视频| 亚洲中文字幕日产无码成人片| 久久毛片少妇高潮| 久久久午夜精品福利内容| 国产口爆吞精在线视频2020版| 亚洲日本高清一区二区三区|