C++基礎知識學習筆記

基本語法ios

C面向過程思想:程序=(數據結構)+(算法)
 數據結構與算法分離,以算法(函數)爲主。c++

C++面向對象思想:程序=(數據結構+算法)
 數據結構(屬性)與算法(操做)綁成一個類,定義一個個對象
對象=(數據結構+算法)  ,程序=(對象+對象+對象+……)程序員

面向對象程序設計的程序員有兩類:
1.面向對象應用程序設計
2.類庫的設計算法

頭文件:類的聲明            ---類的外部接口
       (成員函數在類聲明中實現時,通常很簡短,默認爲內聯函數)
源文件:類的成員函數定義     ---類的內部實現編程


c++新增關鍵字:
namespace  using  class
private protected public
bool true false
this new delete
friend explicit mutable  virtual  operator inline  template
catch throw try
static_cast dynamic_cast const_cast reinterpret_cast數組

1.命名空間
namespace  myspace  //命名空間(至關於聲明一個類)
{
 int num=100;//變量
 void show() //函數
 {
  cout<<"num= "<<num<<endl;
 }
 namespace myspace1
 {
  int num =150;
 }
};緩存

2.iostream.h  C92標準
  iostream    C99標準 std;安全

3.輸入輸出
cin>>   標準輸入
cout<<  標準輸出
cerr<<  標準錯誤輸出
clog<<  錯誤輸出(有緩衝)數據結構


4.布爾類型
   bool flag; 只能存放false 0和true 1 兩種狀態。
   flag = true ;
   flag = false;
   flag = 3 ;此時flag只能爲true(1);app

5.const
const num=12;//只讀變量,定義時必須初始化。


6.引用和指針

區別:
1.非空: 引用不能爲空,定義的時候必須初始化(指針能夠爲空,不初始化)
2.合法性:使用的時候不須要再驗證期合法性。(指針使用的時候須要驗證其合法性)
3.不可修改:初始化對象以後不可修改,但標示的變量值可變。(指針靈活,可隨意修改所指對象及對象值)
4.應用場合:引用通常用在對象固定的單個變量,不能是數組。
5.引用不用分配內存,節省內存空間,適用於較大數據參數傳遞。

int count = 11;
int num = 12;
int &ref = num; //1.同一個內存空間,不一樣的名字 2.定義的時候必須初始化 3.標示對象固定,值可變
ref = count;
const int &ref=num;//常引用:便可提升效率,又保護數據不更改。
注意:char &ref="hello"是不對的,hello是const類型的常字符串,不能轉換爲char類型引用。

void myswap(int *n1, int *n2)//另開闢一指針變量空間存地址,其指向對象可改變,靈活。

void myswap(int &n1, int &n2) //可修改同一塊內存空間的值。簡單方便。但其標示對象不可變。

將「引用」做爲函數參數有哪些特色?
(1)傳遞引用給函數與傳遞指針的效果是同樣的。這時,被調函數的形參就成爲原來主調函數中的實參變量或對象的一個別名來使用,因此在被調函數中對形參變量的操做就是對其相應的目標對象(在主調函數中)的操做。
(2)使用引用傳遞函數的參數,在內存中並無產生實參的副本,它是直接對實參操做;而使用通常變量傳遞函數的參數,當發生函數調用時,須要給形參分配存儲單元,形參變量是實參變量的副本;若是傳遞的是對象,還將調用拷貝構造函數。所以,當參數傳遞的數據較大時,用引用比用通常變量傳遞參數的效率和所佔空間都好。
(3)使用指針做爲函數的參數雖然也能達到與使用引用的效果,可是,在被調函數中一樣要給形參分配存儲單元,且須要重複使用"*指針變量名"的形式進行運算,這很容易產生錯誤且程序的閱讀性較差;另外一方面,在主調函數的調用點處,必須用變量的地址做爲實參。而引用更容易使用,更清晰。


返回引用注意:
(1)不能返回局部變量的引用。主要緣由是局部變量會在函數返回後被銷燬,所以被返回的引用就成爲了"無所指"的引用,程序會進入未知狀態。
(2)不能返回函數內部new分配的內存的引用,雖然不存在局部變量的被動銷燬問題,可對於這種狀況(返回函數內部new分配內存的引用),又面臨其它尷尬局面。例如,被函數返回的引用只是做爲一個臨時變量出現,而沒有被賦予一個實際的變量,那麼這個引用所指向的空間(由new分配)就沒法釋放,形成memory leak。
(3)能夠返回類成員的引用,但最好是const。 主要緣由是當對象的屬性是與某種業務規則(business rule)相關聯的時候,其賦值經常與某些其它屬性或者對象的狀態有關,所以有必要將賦值操做封裝在一個業務規則當中。若是其它對象能夠得到該屬性的很是量引用(或指針),那麼對該屬性的單純賦值就會破壞業務規則的完整性。
(4)流操做符重載返回值申明爲「引用」的做用:
流操做符<<和>>,這兩個操做符經常但願被連續使用;賦值操做符=。這個操做符象流操做符同樣,是能夠連續使用:x=y=10;
(5)在另外的一些操做符中,不能返回引用:+-*/ 四則運算符。它們不能返回引用,主要緣由是這四個操做符沒有side effect,所以,它們必須構造一個對象做爲返回值.


何時須要「引用」?
流操做符<<和>>、賦值操做符=的返回值、拷貝構造函數的參數、賦值操做符=的參數、其它狀況都推薦使用引用

7.內聯函數
編譯的時候直接替換成函數體,不須要分配棧空間,節省了時間。
適合於簡短代碼,不能有while switch等複雜結構流程語句。

#define  A(x)   x   在預處理的時候替換,無參數類型的制約,c++中通常不用
inline  fun1(int a)

inline  string dbtest (int a ,int b)  //聲明的時候加上 inline
void main()

 dbtest(3,4)     
}

string dbtest(int a,int b)   //函數體,適用代碼短,無複雜結構控制語句,無遞歸函數
{
 return a+b;           
}

 

8.內存分配
C:(函數)
//malloc分配的特色:1.按字節分配,返回void類型地址 2.不進行初始化 3.須要#include<stdlib>
int *p;
p = (int *)malloc(100 * sizeof(int));
free(p);
                
C++:new(關鍵字)
在C++中,類的建立若是用malloc則繞過了構造函數,不是一個真正的類建立。只是分配內存而已。
用new申請的是一個類對象的內存空間,調用了構造函數,因爲堆是手動分配,不用的時候須要用delete手動釋放,delete調用析構函數釋放內存空間。否則容易形成內存泄露。反覆new和delete容易形成內存碎片。

若是對象的數據成員包含指向堆空間的指針,必須自定義深拷貝構造函數,須要用new爲建立的對象分配堆空間
通常自定義的拷貝構造函數都須要一個自定義的析構函數來釋放額外的資源。

//new分配的特色:1按對象類型分配,返回對象類型地址 2.默認方式初始化 3.不須要頭文件
Student *p;
p = new Student[5];
delete [] p;  //單一標量時。用 delete p;

A *p=new A; //會調用無參構造
A *p=new A[10];//調用10次無參構造,在堆上分配對象數組,只能調用無參構造,不能在跟參數。
A *p=new A(10); //調用有參構造
A *p=new A(a1);//調用拷貝構造
A *p=new A(*p);//調用拷貝構造

delete [] p;// 調用了析構函數。

**********************************************************************************
                 ---類和對象---


面向過程:C  功能分解,
面向對象(Object Oriented):C++  責任分解
特徵:1.抽象(abstract) 2.封裝(encapsulation)
 3.繼承(inheritance) 4.多態(polymorphism)

類:同類型對象抽象出共性造成類
對象:是類的一個實例,除了具備類的共性之外,還會有本身的特性
關係:類是對象的一種抽象描述,對象是類的實例化

c++中,類與結構體區別:
1.結構體是類的一種特例,class能夠改成struct。
2.未指定訪問權限時,類中成員默認爲私有,而結構體默認爲公有。
3.通常,數據--結構體;  數據+操做行爲--類

this指針:
1.類的全部對象調用的成員函數都是同一段代碼,不一樣對象在調用函數的時候,會傳給函數的隱含形參this指針一個本身的地址,至關於this=&s,這樣函數操做就知道是哪一個對象的數據了,也就是成員函數能夠直接訪問數據成員而無需對象名的緣由。
2.對象的數據在main函數的棧裏,別的函數不能直接訪問,因此要傳入對象的地址。(至關於傳址調用)
3.線程中建立線程函數中的函數參數通常不能是c++的成員函數,由於在類中定義的成員函數編譯的時候會自動加上this指針。(能夠將該函數設定爲static靜態成員函數或者友元函數)


重載:類中容許多個同名不一樣參函數,編譯器根據函數名和參數肯定不一樣的函數調用。
重寫(覆蓋):子類從新定義父類虛函數。遲滯聯編,運行的時候動態調用子類的函數。

類成員函數的重載、覆蓋和隱藏區別?
a.成員函數被重載的特徵:
(1)相同的範圍(在同一個類中);
(2)函數名字相同;
(3)參數不一樣;
(4)virtual 關鍵字無關緊要。
b.覆蓋是指派生類函數覆蓋基類函數,特徵是:
(1)不一樣的範圍(分別位於派生類與基類);
(2)函數名字相同;
(3)參數相同;
(4)基類函數必須有virtual 關鍵字。
c.「隱藏」是指派生類的函數屏蔽了與其同名的基類函數,規則以下:
(1)若是派生類的函數與基類的函數同名,可是參數不一樣。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
(2)若是派生類的函數與基類的函數同名,而且參數也相同,可是基類函數沒有virtual 關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆


類大小:有它數據成員(不含static數據)所佔空間決定。(類的成員函數不佔內存空間)

class  <類名>
{
      public:
                 <公有數據成員和成員函數>;
      protected:
                 <保護數據成員和成員函數>;
    private:
                 <私有數據成員和成員函數>;

};
<各個成員函數的實現>;


---數據成員---

私有成員:private  :自身類(+友元類)
 要訪問:1.加友元friend  2.用接口函數獲得其值。

保護成員:protected :自身類(+友元類)+派生類

共有成員:public:自身類(+友元類)+派生類+其餘類和函數 ==任何代碼


靜態成員:
靜態數據成員:面向對象中使用靜態數據成員替代全局變量,能夠增長安全性和更好的封裝重用特性。
靜態成員函數:
*static數據成員:public:
       static int count;
      int Student::count =88;  //定義和初始化靜態成員。
                  cout<<"count=" <<Student::count<<endl;//類的靜態成員,通常經過類來訪問。
   1. 在類中定義,在類外初始化(加域限定符),放在類的內部實現.cpp文件中。
         (不能放在類聲明裏面,也不能在.cpp文件中main函數前面)。
   2.屬於類,不屬於某個對象,存儲於全局數據區,程序運行前便已分配內存和初始化。
        3.public類型靜態數據能夠在類外共享,private/protected只可在類內部訪問,不能用this限制.
   4.利用類名直接訪問(也能夠利用對象訪問)

        使用場合:通常用在保存流動變化的對象個數,
                 做爲一個標誌指示一個特定動做是否發生,
                 指向一個鏈表的頭結點或尾節點。

 static +成員函數
        1.靜態成員函數中沒有this參數傳入。
   2.通常爲public,使用類名直接調用。

        public:
  static A * createObj()  //用static函數裏new調用構造函數。
  {
   A *obj=new A;     //可調用構造函數
   return obj;
  }
         A * p= A::createObj();     //調用static函數

常成員
const+數據成員:const int num; 
 1.只讀變量。
 2.容許int a[num]
 3.必須在構造函數的初始值表中初始化。
 Student() : num(10) {}
const+成員函數:void fun() const
      不能修改類中的數據成員(除了mutable int a;)

      

this指針:this->name
1.調用成員函數的時候將對象的指針做爲隱含的參數傳到行爲函數中,聯通對象(棧)和函數。使得函數可直接使用對應的對象中的數據成員。
2.this不能用在靜態成員。
    

---成員函數---

構造函數 :類的獨特性使得它對數據成員有保護性,不能隨意賦值來初始化,能夠用一個成員函數來專門進行初始化。爲了方便,則讓他在定義一個對象的時候自動調用特殊的成員函數(即構造函數)進行分配內存和初始化。

類型:
無參構造
有參構造

初始化方式:
a.函數體內賦值(已分配空間)。
b. 經過初始值表在分配空間的同時賦值。A(int _a):a(_a){},通常用於常量和引用。
  注意:構造對象成員的時候,得看類中聲明的順序,不是看冒號後面成員初始化的順序。
加explicit表示確切賦值,阻止隱式賦給對象的成員(A a1=200;)

定義對象:(類的實例化)
Student st1;   //調用無參構造
          //不能是Student st1();由於C++會認爲是聲明瞭一個名叫st1的普通函數,返回Student類型。
Student st2(2,"xiaoming",80); //調用有參構造


1.定義對象的時候自動調用,給對象初始化
2.構造函數名和類名相同,沒有返回類型
3.可重載,根據參數類型和順序自動調用相對應構造函數。
4.默認會生成一個空的無參構造函數,只負責分配內存不進行初始化。(全局爲0,局部爲隨機)
  一旦本身定義一個構造函數,那麼默認的無參構造函數將再也不提供。(記得手動加上無參構造函數)
5.構造函數能夠是private(可利用public中static函數調用private中的構造函數來構造新對象)

無參構造函數
Student() {} 

有參構造函數
Student(int nu, char *na, float sc) {}

拷貝構造函數:
1.使用已經存在的對象來生成新的對象
Student(Student &b){} 
Student st4(st1); //顯式調用拷貝構造函數
Student st5=st2;  //隱式調用拷貝構造函數(不是賦值)

當裏面有指針時:
a.淺拷貝:A(A & _a1)
      {
        this->p=_a1.p;
      }
拷貝後指針指向同一個內存,使用時會發生錯亂。
b.深拷貝:A(A & _a1)
      {
         p=new char[10];
   strcpy(p,_a1);
      }

手動實現拷貝構造函數。連指針指向的對象一塊兒拷貝

2.當函數的形參是類的對象,實參傳遞給形參調用函數的時候。
//String & _s =s1 沒有調用拷貝構造,僅是取了另外一個名字。s表明s1自己;  節約內存。
//String  s=s1;  調用了拷貝構造函數,另分配了臨時空間s;
Book test1(Book b)
{
    return b;
}
test1(book2);
3.函數的返回類型爲對象類型的時候。
String    返回的是一個值, 不能返回局部變量地址,返回一個臨時對象,返回後當即釋放。
String &  返回的是一塊內存,不能是局部變量內存,能夠是全局變量。
String & operator +(String& _s)


析構函數
1.釋放對象以前自動調用,手動釋放堆,按棧的順序(先構造後釋放)釋放內存空間。
2.函數名爲~類名,沒有返回類型
3.,沒有參數,不能夠重載
4.默認會生成一個空的析構函數。
5.析構函數必須是public

其餘自定義接口函數:
 float get_score() //讀取數據成員,對於類中只包含有get而不包含有set的屬性叫只讀屬性
 {
     return score;
 }
 void set_score(float sc)  //修改數據成員,包含有set方法的數據成員叫作可寫的屬性
 {
         score = sc;
 }

帶有默認值參數的函數
省去了多個函數因參數不一樣而進行重載,默認值的參數通常是從右到左
int add(int a=2,int b=1) {}
cout<<add(10,20)<<endl;
cout<<add(10)<<endl;


友元:
 友元超越了類的封裝,在類外容許訪問類的私有數據成員,帶來性能提高和編程的靈活性。  
 1.友元函數(普通函數 + 類的成員函數)
 函數聲明在類聲明中,實現必須放在要訪問的類的實現以後。(注意:不屬於類的成員函數)
 friend float avg_score(Student *ps, int count);
 friend void Teacher::set_stu_score(Student &ps, float sc);

 2.友元類:能夠用該類全部成員函數訪問私有數據成員
 該友元類的定義應放在有私有數據聲明前面。
 friend class Teacher;

     
          ­
*******************************************************************************
                ---類的繼承和派生---

父類(基類)
 ↓
子類(派生類)
1.實現繼承:所有繼承,無需額外編碼
2.接口繼承:僅使用屬性和方法,在子類中實現(抽象基類)
2.可視繼承:子窗體使用父窗體的外觀和實現代碼


子類聲明:
此時,子類擁有了父類的屬性和方法,還能夠本身添加獨有的屬性和方法,也能夠從新實現或重載。

單繼承格式:
class  <派生類名> :<繼承方式> <基類名>
{
 public: //派生類新定義成員
 protected:
 private:
}

1.繼承的方式--數據成員的訪問權限:

private  :公有,保護-> 私有 (基類中私有數據不能在派生類中訪問,更不能在其餘類和函數中訪問)

protected:公有 -> 保護     (基類中保護數據能夠在派生類中訪問,不能在其餘類和函數中訪問  )

public:   全部不變。        (基類中公有數據能夠在派生類中訪問,也能夠在其餘類和函數中訪問)

1.私有數據在任何方式下繼承都是不能訪問的。
2.保護數據在私有繼承的狀況下只能在派生類中訪問,繼續繼承則不能訪問了。
3.公有數據在公有繼承狀況下都能訪問。

2.構造函數的實現方式:
注意: 1.派生類不能初始化基類中的私有數據。
 2.默認爲先調用基類的無參構造函數,再調用派生類的構造函數。
因此:通常能夠指定調用基類構造函數的方式(注意按照基類構造函數的參數順序進行傳遞)。
 使得用合適的基類構造基類的數據,派生類構造派生類的數據。
Car::Car(float ai, float sp, int to) : Vehicle(to, sp)

3.成員函數的實現方式:
a.僅繼承基類的成員函數
  則直接調用基類的版本。

b.對基類成員函數進行了從新的實現(同名同參)
基類函數沒有virtual關鍵字,原來的基類成員函數被隱藏
只調用派生類的成員函數   lex.show();
能夠經過基類名::成員函數 的方式調用基類的版本。
lex.Vehicle::show();

c.對基類成員函數進行了從新的實現(同名不一樣參)
無論基類函數有沒有virtual關鍵字,原來的基類成員函數被隱藏
只能調用派生類的成員函數  lex.stop(3);
能夠經過基類名::成員函數 的方式調用基類的版本。
lex.Vehicle::stop();

 

多態
同一個基類有多個派生類,每一個派生類有相同方法名,不一樣方法體,容許將子類的地址賦值給父類指針或引用。
多態實現條件:
1.必須是公有繼承
2.必須是基類指針或引用對象
3.必須是虛函數

多態的做用:
1)隱藏實現細節,使得代碼可以模塊化;擴展代碼模塊,實現代碼重用;
2)接口重用,爲了類在繼承和派生的時候,保證使用家族中任一類的實例的某一屬性時的正確調用

基類指針或引用能夠指向派生類對象
base1 *c1=new child;
c1->fun();

虛函數
virtual修飾的基類方法
一樣一個操做,在繼承中的不一樣對象經常須要不一樣的實現。好比學生和研究生的學費計算。稱爲多態。
基類和子類都是屬於基類的,用基類的指針或引用調用基類和子類都有的同名同參的函數時,須要根據不一樣的對象類型調用不一樣的函數,用virtual表示該函數爲遲後聯編(late binding),運行的時候才知道調用哪一個對象的函數。這樣即可實現用一個函數操做即可以管理全部的繼承的對象。
1.只有成員函數才能是虛函數,靜態成員函數、內聯函數、構造函數不能是虛函數。
2.析構函數須要針對不一樣對象析構不一樣對象,能夠是虛函數。

1.虛函數在基類中必須實現函數。
2.虛函數能夠被派生類重寫,沒有重寫時調用基類函數。

純虛函數
程序在功能分解過程當中,高層次的類只用來繼承,沒有必要實例化,稱爲抽象類,抽象類爲其餘類繼承服務。
其子類對其純虛函數進行了實現,則不是抽象類了。
裏面的函數只有聲明沒有實現,稱爲純虛函數。純虛函數爲子類保留一個位置,使得在多態中可使用子類的實在函數覆蓋原來的位置。否則基類的指針找不到該成員函數會報錯。
方法體爲0的虛函數,在每一個派生類(要實例化)中必須實現函數。
virtual char* what()=0;

抽象類
只要包含有一個純虛函數的類爲抽象類
1.抽象類通常爲基類
2.抽象類能夠包含其餘的實虛函數
3.抽象類不能被實例化,但能夠聲明一個抽象類的指針或引用。
4.派生類若是沒有重寫基類的純虛函數,該派生類也爲抽象類

 

動態聯編與靜態聯編
動態聯編和靜態聯編只能在多態時使用
動態聯編:在調用時,肯定基類指針指向對象
靜態聯編:在編譯時,肯定基類指針所指對象


虛函數表

類大小計算

1.沒有數據成員大小爲1
2.沒有虛函數的類,只給非靜態成員變量分配空間
3.派生類繼承基類的全部成員大小
4.有虛函數的基類會多分配4個字節大小存放虛表地址
5.派生類繼承全部基類的存放虛表地址空間
6.派生類本身的方法再也不分配空間,替換基類的方法或默認添加到第一個基類虛表後面

虛表(v-table)
保存類中虛函數的地址
包含虛函數類的對象:前四個字節確定是虛表地址


多繼承
一個子類繼承多個父類:
1.編譯程序問題:構造的順序
2.模糊性問題:多個基類具備相同方法名,到底調用哪個。

虛基類
主要是用來解決多個基類具備相同的方法名的問題,派生類繼承多個基類時,發現存在虛基類則構造,後加入的虛基類用前面的那個。
class  base
class base1:virtual public base
class base2:virtual public base
class child:public base1,public base2
包含虛基類構造順序:
1.首先構造虛基類
2.構造非虛基類


**********************************************************************************
        ---模板---

函數模板
函數模板避免了針對相同操做、不一樣數據類型須要屢次重載不一樣的函數的侷限。
template<class T,class T1,.....>
T fun(T a,T1 b)
{
    ...
}
函數模板:聲明瞭一個通用類型參數的函數,編譯時不爲其產生任何代碼。
模板函數:編譯系統發現具體的函數調用的時候自動匹配,找到函數模板就重載一個實際的模板函數。

類模板
在定義類時,類中的數據類型能夠不肯定,可是在實例化對象時指定數據類型

C++中爲何用模板類:
 (1)可用來建立動態增加和減少的數據結構
(2)它是類型無關的,所以具備很高的可複用性。
(3)它在編譯時而不是運行時檢查數據類型,保證了類型安全
(4)它是平臺無關的,可移植性
(5)可用於基本數據類型

template<class T,class T1>
class A
{
 public:
  A(T _a,T1 _b);
     T1 max();
  T min();
 private:
  T a;
     T1 b;
};
  template<class T,class T1>
  T1 A<T,T1>::max()
  {
     return b;
  }

A<int,char> a1(2,'a'); //實例化類對象時必需要指定數據類型     

函數模板與類模板有什麼區別:
函數模板的實例化是由編譯程序在處理函數調用時自動完成的,而類模板的實例化必須由程序員在程序中顯式地指定。

友元模板類

templat<class T>
clas B;//前置聲明B爲模板類

template <class T>
class A
{
    friend class B<T>;  //說明模板類B爲友元類
};
template <class T>
class B
{
}

模板類繼承


異常處理

異常
正在運行程序發生錯誤
異常是可能也可能不發生,根據程序運行的環境或輸入值有關
一旦發生異常,程序中止運行,不會退出程序

異常處理:
1.拋出異常  throw
2.捕捉異常  try
3.處理異常  catch

try
{
    throw except("b==0 is error"); //拋出異常
}

catch(base& e)
{
    cout<<e.what()<<endl;
}


c++如何調用c的函數

c++是一種不完全的面嚮對象語言,爲了和c兼容,它能夠定義不屬於任何類的全局變量和函數。
可是爲了支持函數的重載,C++對函數的處理方式爲:
int add(int a,int b)
c++編譯以後函數爲: add_int_int
c編譯以後函數爲:add

通常文件結構:
#ifndef __INCxvWorksh
#define __INCxvWorksh

#ifdef __cplusplus
extern "C"
{
#endif

/*C code*/

#ifdef __cplusplus
}
#endif

extern "C":1.按照c編譯語法編譯
           2.extern表示它修飾的全局變量和函數能夠在本模塊和其餘模塊中使用


判斷一段程序是由C 編譯程序仍是由C++編譯程序編譯的:
#ifdef __cplusplus
cout<<"c++";
#else
cout<<"c";
#endi

//指向對象的數據成員指針
int *p=&(a1.x);
cout<<*p<<endl;

//指向類中的成員函數指針
int (A::* fun) ();  
fun=&A::getX;
cout<<(a1.*fun)()<<endl;


符號重載(重寫)
符號重載:給符號賦予新的功能
至關於一個特殊的成員函數或者友元函數,只是函數名爲符號。
s1+s2至關於 s1.+(s2)  :s1調用 名字爲‘+’的成員函數

符號
運算符號:+ - * / %
比較符號:> >= <  <= != ==
邏輯符號:&& ||
位運算符號:& | ^ ~
賦值符號:= += -=
特殊符號:[] . , :: -> * &


可用做重載的運算符:
 算術運算符:+,-,*,/,%,++,--
  位操做運算符:&,|,~,^,<<,>>
  邏輯運算符:!,&&,||;
  比較運算符:<,>,>=,<=,==,!=;
  賦值運算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
  其餘運算符:[],(),->,,(逗號運算符)

不能重寫的符號:
 .
 ::
 *
 ?:
 sizeof

符號重寫語法:
返回值類型  operator  重寫符號(參數)

符號重載方式:
1.類的成員方式重載
2.友元函數方式重載
 
符號重寫特色:
1.不能改變符號的結合性
2.不能改變符號的優先級
3.不能改變符號元數(一元符號 二元符號)
4.不能創造符號

類的成員方式重寫與友元方式重寫特色:
a.類的成員方式重寫特色
  1.一元符號,能夠寫成無參數(this指針代替)
  2.二元符號,能夠寫成只有一個參數(this指針代替另外一參數)
  3. =,(),[] 和-> 只能是成員方式重寫
b.友元方式重寫特色
  1.一元符號,必須有一個參數
  2.二元符號,必須兩個參數
  3.<<, >>只能使用元方式重寫

 

C++流

全部流的基類:ios(抽象類) -->istream ,ostream ,fstreambase,strseambase
  istream +fstreambase --> ifstream
  ostream +fstreambase --> ofstream

  istream +strseambase --> istrstream
  ostream +strseambase --> ostrstream 

  istream +ostream  --> iostream
  iostream+fstreambase  --> fstream
  iostream+strseambase  --> strstream

頭文件:iostream: ios,istream,ostream,iostream,
   fstream : fstreambase,ifstream,ofstream,fstream, +<iostream>
       strstream:strstreambase,istrstream,ostrstream,strstream +<iostream>

標準輸入輸出流:istream ostream iostream

文件流:ifstream(讀文件) ofstream(寫文件) fstream
文件(鍵盤)  ==》 內存   讀入   in
文件(屏幕) 《==  內存   寫出   out
字符串流: istrstream  ostrstream  strstream

 

輸入/輸出流的控制
輸入流:cin
輸出流:cout cerr  clog(日誌)
cout:標準輸出,與緩存關聯
cerr:錯誤輸出,無緩存
clog:日誌輸出,與緩存關聯

'\n' endl  回車 清空緩存

#include<iomanip> 輸入輸流控制的頭文件
輸入輸出流的控制符
#include<iomanip>   I/O流控制頭文件
dec                                              設置整數的基數爲10
hex                                              設置整數的基數爲16
oct                                              設置整數的基數爲8
setfill(c)                                       設置填充字符c,c能夠是字符常量或字符變量
setprecision(n)                                  設置有效數字個數
setw(n)                                        設置字段寬度爲n位

setiosflags(ios::scientific)                     設置浮點數以科學計數法(即指數)顯示
setiosflags(ios::left)                           輸出數據左對齊   
setiosflags(ios::right)                          輸出數據右對齊   
setiosflags(ios::uppercase)                      在以科學計數法輸出E和以十六進制輸出字母X時以大寫表示
setiosflags(ios::showpos)                       輸出正數時給出「+」號

控制輸出格式的流成員函數
precision(n)    設置實數的精度爲n位
width(n)        設置字段寬度爲n位
fill(c)         設置填充字符c
setf()          設置輸出格式狀態  
unsetf()        終止已設置的輸出格式狀態     


格式狀態標誌
 
ios_base::left
左對齊輸出,用於輸出
 
ios_base::right
右對齊輸出,用於輸出
 
 
ios_base::dec
轉換基數爲十進制,用於輸入或輸出
 
ios_base::oct
轉換基數爲八進制,用於輸入或輸出
 
ios_base::hex
轉換基數爲十六進制,用於輸入或輸出
 
ios_base::showbase
輸出時顯示基指示符(0表示八進制,0x或0X表示十六進制),用於輸入或輸出
 
 
ios_base::uppercase
輸出時表示十六進制的x爲大寫,表示浮點數科學計數法的e爲大寫,用於輸出
 
ios_base::showpos
正整數前顯示「+」符號,用於輸出
 
ios_base::scientific
用科學表示法顯示浮點數,用於輸出
 

 

 


文件流:
ifstream:讀文件
ofstream:寫文件

文件流操做文件模式:
ios::in:讀文件
ios::out:寫文件(建立文件,清空間文件,寫入)
ios::app:寫文件追加
ios::ate:寫文件追加
ios::binary:二進制文件
ios::trunc:清空文件內容

out,trunc和app模式只能用於指定與ofstream或fstream對象關聯的文件

in模式只能用於指定與ifstream或fstream對象關聯的文件

流構造:
ifstream(char* filename,mode)

關閉流
close(ifstream)//清空緩存(緩存中的內容寫入到文件)


get
語法:
  istream &get( char &ch );
  istream &get( char *buffer, streamsize num );
  istream &get( char *buffer, streamsize num, char delim );

get()函數被用於輸入流:
讀入一個字符並把它存儲在ch,
讀取字符到buffer直到num - 1個字符被讀入, 或者碰到EOF或換行標誌,
讀取字符到buffer直到已讀入num - 1 個字符,或者碰到EOF或delim(delim直到下一次不會被讀取)


getline
語法:
  istream &getline( char *buffer, streamsize num );
  istream &getline( char *buffer, streamsize num, char delim );

getline()函數用於輸入流,讀取字符到buffer中直到下列狀況發生:
num - 1個字符已經讀入,
碰到一個換行標誌,
碰到一個EOF,
或者,任意地讀入,直到讀到字符delim。delim字符不會被放入buffer中。


塊讀寫
read(char * buf,int size);//通常與輸入流使用
write(char * buf,int size);//通常是與輸出流使用

size:寫入或讀取的字節數(n*sizeof(class))


標準模板庫

C++:1:面向對象設計思想,抽象封裝,繼承多態,標準類庫
     2:泛型程序設計思想(generic programming),模板機制,STL

STL :Standard Template Library(數據結構+算法)
容器 :可容納各類數據類型的數據結構。
算法:用來操做容器中的元素的算法函數。

容器
分類:
第一類容器:
1.順序容器:vector,list,deque
2.關聯容器:set(multiset)  map(multimap) (key)

第二類容器:
3.容器適配器:stack,queue,priority_queue

vector
1.vector是一種順序容器,元素是存放在一段連續空間。
2.至關於可以存聽任意類型的動態數組,代替C類型的。
3.在數組末尾增刪元素時間固定,中間增刪時間與該元素後面個數成正比。
4.支持隨機存儲。
5.能夠用下標[],at(),迭代器訪問,at在運行時會檢查容器大小,更安全。

構造vector
 vector();                                          //無參構造
 vector(size_type num, const TYPE &val );           //有參,放入num個val
 vector( const vector &from );                      //拷貝構造
 vector( input_iterator start, input_iterator end );//[start,end)區間元素
讀取:
 begin(); //返回第一個元素的迭代器
 end(); //指向當前vector末尾元素的下一位置的迭代器

 rend();  // 返回Vector起始的逆迭代器
 rbegin();// 返回Vector尾部的逆迭代器
 
 TYPE at( size_type loc );//返回當前Vector指定位置loc的元素的引用.
     //v.at(i)
 front(); //返回第一個元素
 back();  //返回最後一個元素

增:
 void push_back( const TYPE &val ); //存放元素到容器末尾
  //push_back(20);
 iterator insert( iterator loc, const TYPE &val );
  //vector<int>::iterator it1=v1.insert(it,2000);//插入新元素到it指定元素前面
  //cout<<*it1<<endl;//返回值爲迭代器執行插入元素位置 
      void insert( iterator loc, size_type num, const TYPE &val );
  //v1.insert(it,5,1);//在it所指元素前插入5個1;
      void insert( iterator loc, input_iterator start, input_iterator end );
  //v1.insert(it,v2.begin(),v2.end());//在指定位置it前插入區間[begin, end)的全部元素

刪:
 pop_back();  //移除容器的末尾元素
 clear();     //清空全部元素

 iterator erase( iterator loc );  //刪除指定元素
  v1.erase(v1.begin()+3);//經過迭代器刪除容器中的元素
      iterator erase( iterator start, iterator end );
  v1.erase(v1.begin(),v1.begin()+4);//刪除指定區間元素
改:
 void assign( input_iterator start, input_iterator end ); //將區間[start, end)的元素賦到           當前vector
   void assign( size_type num, const TYPE &val );//賦num個值爲val的元素到vector中

 void swap( vector &from );//swap()函數交換當前vector與vector from的元素
  v1.swap(v5);//交換容器

查:
 #include <algorithm>   find爲宏函數
  vector<int>::iterator it=find(v1.begin(),v1.end(),20);//查找find(算法函數)
  判斷元素是否存在
     if(it==v1.end())
   cout<<"not find"<<endl;
  else
             v1.erase(it);

運算:v1 == v2   1.它們具備相同的容量  2. 全部相同位置的元素相等
   v1 != v2
   v1 <= v2
   v1 >= v2
   v1 < v2
   v1 > v2
   v[]

其餘:
 size();    // 返回Vector元素數量的大小
  void resize( size_type size, TYPE val ); //改變Vector元素數量的大小
 max_size();// 返回Vector所能容納元素的最大數量(上限)
 capacity();//返回vector所能容納的元素數量(在不從新分配內存的狀況下)
 empty();   // 判斷Vector是否爲空(返回true時爲空)

 

 


迭代器
是一個自定類型,指向容器中元素的指針,每一種容器都有對應迭代器
 
迭代器分類:
1.通常迭代器
通常迭代器定義
vector<int>::iterator it;
2.只讀迭代器(只能訪問容器元素,不能修改)
只讀迭代器定義
vector<int>::const_iterator it;
3.反轉迭代器
反轉迭代器定義
vector<int>::reverse_iterator it;

list 鏈表容器
1.元素按順序儲存在鏈表中.與向量(vectors)相比, 它容許快速的插入和刪除,可是隨機訪問卻比較慢.
2.能夠存聽任何數據類型的動態鏈表
3.在任何位置插入刪除都是常數時間
4.不支持隨機存儲。
5.

    
構造
 list()
 list(list& l)
 list(a,a+3);

在順序容器中新增長的函數:

push_front: 在前面插入
pop_front: 刪除前面的元素
merge: 合併兩個鏈表,並清空被合併的那個
sort: 排序( list 不支持STL 的算法sort)
reverse: 顛倒鏈表
remove: 刪除和指定值相等的全部元素
unique: 刪除全部和前一個元素相同的元素
splice: 在指定位置前面插入另外一鏈表中的一個或多個元素,並在另外一鏈表中刪除被插入的元素


pair 
pair<int,string>
pair<list<int>::iterator,list<int>::iterator>


set關聯容器
有序存放元素值
set容器構造
set<int> s1;
set<int,cmp>
set容器中元素值必定是惟一

multiset關聯容器與set容器功能同樣,但容許出現相同值的元素

map
一種key-value元素對容器
map<key,value>
key特色:
1.只讀
2.惟一
3.根據key排序

map構造
map<string,int>

multimap關聯容器與map容器功能同樣,容許出現相同鍵值

練習:1.實現vector list容器

相關文章
相關標籤/搜索