日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++基础知识学习笔记

發布時間:2025/3/14 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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);

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容器

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?


?

轉載于:https://www.cnblogs.com/liaoyi425/p/3766517.html

總結

以上是生活随笔為你收集整理的C++基础知识学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。