c++學(xué)習(xí)筆記

第一天

一.內(nèi)聯(lián)函數(shù)(inline)

函數(shù)調(diào)用的時(shí)候需要建立棧內(nèi)存環(huán)境,進(jìn)行參數(shù)傳遞,并產(chǎn)生程序執(zhí)行轉(zhuǎn)移,這些工作都需要一些時(shí)間開銷。有些函數(shù)使用頻率高,但代碼卻很短。

c++提供inline函數(shù),減少了函數(shù)調(diào)用的成本

遇到inline函數(shù)時(shí)直接采用替換的方式,而不用在棧上創(chuàng)建相應(yīng)環(huán)境


二.宏定義

2.1? #define的概念

#define命令是C語(yǔ)言中的一個(gè)宏定義命令,它用來(lái)將一個(gè)標(biāo)識(shí)符定義為一個(gè)字符串,該標(biāo)識(shí)符被稱為宏名,被定義的字符串稱為替換文本。

該命令有兩種格式:一種是簡(jiǎn)單的宏定義,另一種是帶參數(shù)的宏定義。

參照:

http://blog.chinaunix.net/uid-21372424-id-119797.html

例1#defineN 2+2

void main()

{

inta=N*N;

printf(“%d”,a);

}

在此程序中存在著宏定義命令,宏N代表的字符串是2+2,在程序中有對(duì)宏N的使用,一般同學(xué)在讀該程序時(shí),容易產(chǎn)生的問(wèn)題是先求解N為2+2=4,然后在程序中計(jì)算a時(shí)使用乘法,即N*N=4*4=16,其實(shí)該題的結(jié)果為8,為什么結(jié)果有這么大的偏差?

(2) 問(wèn)題解析:

如1節(jié)所述,宏展開是在預(yù)處理階段完成的,這個(gè)階段把替換文本只是看作一個(gè)字符串,并不會(huì)有任何的計(jì)算發(fā)生,在展開時(shí)是在宏N出現(xiàn)的地方 只是簡(jiǎn)單地使用串2+2來(lái)代替N,并不會(huì)增添任何的符號(hào),所以對(duì)該程序展開后的結(jié)果是a=2+2*2+2,計(jì)算后=8,這就是宏替換的實(shí)質(zhì),如何寫程序才能完成結(jié)果為16的運(yùn)算呢?

/*將宏定義寫成如下形式*/

#defineN(2+2)

/*這樣就可替換成(2+2)*(2+2)=16*/


#define area(x)x*x

/*這在使用中是很容易出現(xiàn)問(wèn)題的,看如下的程序*/

voidmain()

{

inty=area(2+2);

printf(“%d”,y);

}

按理說(shuō)給的參數(shù)是2+2,所得的結(jié)果應(yīng)該為4*4=16,但是錯(cuò)了,因?yàn)樵摮绦虻膶?shí)際結(jié)果為8,仍然是沒(méi)能遵循純粹的簡(jiǎn)單替換的規(guī)則,又是先計(jì)算再替換 了,在這道程序里,2+2即為area宏中的參數(shù),應(yīng)該由它來(lái)替換宏定義中的x,即替換成2+2*2+2=8了。那如果遵循(1)中的解決辦法,把2+2 括起來(lái),即把宏體中的x括起來(lái),是否可以呢?#define area(x) (x)*(x),對(duì)于area(2+2),替換為(2+2)*(2+2)=16,可以解決,但是對(duì)于area(2+2)/area(2+2)又會(huì)怎么樣呢,有的學(xué)生一看到這道題馬上給出結(jié)果,因?yàn)榉肿臃帜敢粯樱皱e(cuò)了,還是忘了遵循先替換再計(jì)算的規(guī)則了,這道題替換后會(huì)變?yōu)?(2+2)*(2+2)/(2+2)*(2+2)即4*4/4*4按照乘除運(yùn)算規(guī)則,結(jié)果為16/4*4=4*4=16,那應(yīng)該怎么呢?解決方法是在整個(gè)宏體上再加一個(gè)括號(hào),即#define? area(x) ((x)*(x)),不要覺(jué)得這沒(méi)必要,沒(méi)有它,是不行的。要想能夠真正使用好宏定義,那么在讀別人的程序時(shí),一定要記住先將程序中對(duì)宏的使用全部替換成它所代表的字符串,不要自作主張地添加任何其他符號(hào),完全展開后再進(jìn)行相應(yīng)的計(jì)算,就不會(huì)寫錯(cuò)運(yùn)行結(jié)果。

如果是自己編程使用宏替換,則在使用簡(jiǎn)單宏定義時(shí),當(dāng)字符串中不只一個(gè)符號(hào)時(shí),加上括號(hào)表現(xiàn)出優(yōu)先級(jí),如果是帶參數(shù)的宏定義,則要給宏體中的每個(gè)參數(shù)加上括號(hào),并在整個(gè)宏體上再加一個(gè)括號(hào)??吹竭@里,不禁要問(wèn),用宏定義這么麻煩,這么容易出錯(cuò),可不可以摒棄它, 那讓我們來(lái)看一下在C語(yǔ)言中用宏定義的好處吧。

常用系統(tǒng)宏

_LINE_/*(兩個(gè)下劃線),對(duì)應(yīng)%d*/ 哪一行

_FILE_/*對(duì)應(yīng)%s*/哪一個(gè)文件

_DATE_/*對(duì)應(yīng)%s*/什么日期

_TIME_/*對(duì)應(yīng)%s*/什么時(shí)間

_func_調(diào)用的哪一個(gè)函數(shù)

總結(jié)

宏定義就是復(fù)制,在程序編譯的時(shí)候會(huì)做一個(gè)替換,所以每一個(gè)參數(shù)都要加括號(hào),如果是帶參數(shù)的表達(dá)式作為宏的話,則整個(gè)表達(dá)式需要加括號(hào)

三.帶參數(shù)的函數(shù)

int foo(int i = 5,int j= 6){

return 0;

}

int foo1(int = 4,int =8){}

四.函數(shù)重載

重載就是函數(shù)的名字相同,但是參數(shù)不同??梢詫?shí)現(xiàn)不同類型的相同的類型

五.函數(shù)模板

1 ?泛型編程

獨(dú)立于任何特定類型的方式編寫代碼(c,oo,stl、boost)

模板是泛型編程的基礎(chǔ)

1.模板使程序員能夠快速建立具有類型安全的類庫(kù)集合和函數(shù)集合,他的實(shí)現(xiàn)方便了大規(guī)模的軟件開發(fā)

2.現(xiàn)有的框架大多都使用了模板(MFC)

類模板+函數(shù)模板

函數(shù)模板

template <類型形式參數(shù)>返回類型 FunctionName(形式參數(shù)表){

//函數(shù)定義體

}

template <typename T> T myFunc(T a ,T b){

if(a>b){?

return a;

}else{

return b;

}

}

//函數(shù)模板

template

T absL(T x) {

returnx <0? -x : x;

}

函數(shù)模板與函數(shù)重載的區(qū)別在于,函數(shù)模板在實(shí)例化后只能進(jìn)行相同的操作,而函數(shù)重載的話在函數(shù)體內(nèi)可以進(jìn)行不同的操作。

六.類和對(duì)象

1、程序化程序設(shè)計(jì)

1.1程序 = 算法 + 數(shù)據(jù)結(jié)構(gòu)

1.2算法第一,數(shù)據(jù)結(jié)構(gòu)第二

2.面向?qū)ο蟪绦蛟O(shè)計(jì)

2.1 程序 = 對(duì)象+ 對(duì)象+。。

2.2關(guān)鍵:讓每一個(gè)對(duì)象負(fù)責(zé)執(zhí)行一組相關(guān)任務(wù)

3 面向?qū)ο缶幊涕_發(fā)范式的特性

3.1萬(wàn)物皆對(duì)象

3.2程序是一組對(duì)象彼此之間在發(fā)送消息

3.3 每個(gè)對(duì)象獨(dú)有自己的內(nèi)存占用,可以組裝成更大的對(duì)象

3.4每個(gè)對(duì)象都有類型性,特定類型的所有對(duì)象可以接收相同的消息

4 概念

類: 類是創(chuàng)建對(duì)象的模板和藍(lán)圖

對(duì)象:對(duì)象是類的實(shí)例化結(jié)果

對(duì)象是實(shí)實(shí)在在的存在,代表世界的某一事物

5 對(duì)象的三大關(guān)鍵特性

行為:對(duì)象能做什么

狀態(tài):對(duì)象的屬性,行為的結(jié)果

標(biāo)識(shí):對(duì)象的唯一身份

類和對(duì)象的區(qū)別

類是靜態(tài)的定義

對(duì)象是動(dòng)態(tài)的實(shí)例

程序操作的是對(duì)象而非類

建模得到的是類而不是對(duì)象

類和對(duì)象的聯(lián)系

類是對(duì)象的抽象

對(duì)象的產(chǎn)生離不開類這個(gè)模板

類存在的目的是實(shí)例化得到對(duì)象

定義一個(gè)類的步驟

1.定義類名

2.編寫類的數(shù)據(jù)成員代表屬性

3.編寫類的方法代表行為

類的建模是一個(gè)抽象和封裝的過(guò)程

抽象:去掉不關(guān)注的,次要的信息而保留重要的信息

封裝:信息打包

具體一點(diǎn):將數(shù)據(jù)和行為結(jié)合在一個(gè)包中,對(duì)對(duì)象的使用者影藏?cái)?shù)據(jù)的實(shí)現(xiàn)方式

實(shí)現(xiàn)封裝的關(guān)鍵:不能讓類中的方法直接訪問(wèn)其他類的內(nèi)部數(shù)據(jù),只能通過(guò)公開的行為間接訪問(wèn)

結(jié)構(gòu)體和類的差別

結(jié)構(gòu)體中的屬性都是共有的,而類中的屬性默認(rèn)是私有的,有多種模式可選

結(jié)構(gòu)體的安全性不好

類不僅可以保護(hù)數(shù)據(jù),還可以提供成員函數(shù)操作數(shù)據(jù)

c++中用類來(lái)抽象數(shù)據(jù)類型(ADT)

class name{

private:

私有的成員

私有的函數(shù)

protect:

public:


};


類的.h文件寫法,注意防止重復(fù)包含頭文件的寫法

類的.cpp文件,注意你要寫這個(gè)類的域名,寫了才可以直接使用它的屬性


Carcar1 ;

car1.setProperty(2,4);

car1.run();


#ifndef car_hpp

#define car_hpp

#include

#include

classCar {

public:

voidrun();

voidstop();

voidsetProperty(intprice,intcarNum);

private:

intprice;

intcarNum;

};

#endif/* car_hpp */




#include"car.hpp"

voidCar:: stop(){

std::cout<<__FILE__<<__LINE__<<__func__<

std::cout<<"stop"<

}

voidCar:: run(){

std::cout<<__FILE__<<__LINE__<<__func__<

std::cout<

}

voidCar::setProperty(intprice,intcarNum)

{

//這些都是對(duì)象方法,當(dāng)對(duì)象調(diào)用這個(gè)方法的時(shí)候,這個(gè)this指針就是對(duì)象的內(nèi)存地址

this->price= price;

this->carNum= carNum;

//也可以直接用的,但是要區(qū)分開才行類屬性和零時(shí)參數(shù)

//price = price ;

//carNum = carNum;

}


封裝

類背后隱藏的思想是數(shù)據(jù)的抽象和封裝

信息隱藏,隱藏對(duì)象的實(shí)現(xiàn)細(xì)節(jié),不讓外部直接訪問(wèn)到

將數(shù)據(jù)成員和函數(shù)封裝到一個(gè)單元中,單元以類的形式實(shí)現(xiàn)

將數(shù)據(jù)成員和成員函數(shù)包裝進(jìn)類中,加上具體實(shí)現(xiàn)的隱藏,共同被稱作封裝,其結(jié)果是一個(gè)同時(shí)帶有特征和行為的數(shù)據(jù)類型。

定義類,定義其數(shù)據(jù)成員,成員函數(shù)的過(guò)程稱為封裝類

信息隱藏是oop最重要的功能之一,也是訪問(wèn)修飾符的原因

信息隱藏的原因包括:


對(duì)模塊的任何細(xì)節(jié)所做的更改不會(huì)影響使用該模塊的代碼

防止用戶意外修改數(shù)據(jù)

使模塊易于使用和維護(hù)


除非必須公開底層實(shí)現(xiàn)細(xì)節(jié),否則應(yīng)該將所有字段指定為private加以封裝

使數(shù)據(jù)成員私有,控制數(shù)據(jù)訪問(wèn)限制,增強(qiáng)了類的可維護(hù)行

隱藏方法的實(shí)現(xiàn)細(xì)節(jié)(方法體),向外部提供公開的接口(方法頭),以供安全使用

程序開發(fā)人員按角色分為類創(chuàng)建者和客戶端(應(yīng)用)程序員

客戶端(應(yīng)用)程序員目標(biāo):收集各種用來(lái)實(shí)現(xiàn)應(yīng)用開發(fā)的類

類創(chuàng)建者目標(biāo):構(gòu)建類,向應(yīng)用程序員暴露必須的部分,隱藏其他部分

在任何相互關(guān)系中,具有關(guān)系所色劑的各方都遵守的邊界,創(chuàng)建類就建立了與客戶端(應(yīng)用)程序員之間的關(guān)系

封裝及其訪問(wèn)控制首要存在的原因:讓客戶端(應(yīng)用)程序員無(wú)法接觸到他們不應(yīng)該接觸到的部分---隱藏細(xì)節(jié)

封裝及訪問(wèn)控制的第二個(gè)原因:允許創(chuàng)建者改變類內(nèi)部的工作方式二不用擔(dān)心會(huì)影響到客戶端的(應(yīng)用)程序員--隔離變化,利于維護(hù)

補(bǔ)充:

c++中類的實(shí)現(xiàn)可以寫在類的里面(定義即實(shí)現(xiàn)),也可以寫在類的外部,只要加上類的作用域就行。在給成員變量賦值的時(shí)候可以使用this指針(代表調(diào)用該方法的類對(duì)象的地址),也可以直接給屬性賦值

this指針是的值就是對(duì)象起始地址的值,this指針就是指向調(diào)用該方法的對(duì)象??梢酝ㄟ^(guò)指針訪問(wèn)符號(hào)->對(duì)對(duì)象的屬性進(jìn)行訪問(wèn),函數(shù)的調(diào)用this->func。

第二天


1 構(gòu)造函數(shù)與析構(gòu)函數(shù)

int i = 0;

int * p = null;//null就是0

類的對(duì)象的初始化只能由類的成員函數(shù)來(lái)進(jìn)行

建立對(duì)象的同時(shí),自動(dòng)調(diào)用構(gòu)造函數(shù)

類對(duì)象的定義涉及到一個(gè)類名和一個(gè)對(duì)象名

由于類的唯一性和對(duì)象的多樣性,用類名而不是對(duì)象名來(lái)作為構(gòu)造函數(shù)名是比價(jià)合適的

默認(rèn)構(gòu)造函數(shù)

c++規(guī)定,每個(gè)類必須有一個(gè)構(gòu)造函數(shù)

默認(rèn)構(gòu)造函數(shù)

只要定義了一個(gè)構(gòu)造函數(shù),c++就不提供默認(rèn)的構(gòu)造函數(shù)

與變量定義類似,在默認(rèn)構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),如果創(chuàng)建的是全局對(duì)象或靜態(tài)對(duì)象,則對(duì)象的位模式全為0,否則對(duì)象是隨機(jī)的

構(gòu)造函數(shù)負(fù)責(zé)對(duì)象的初始化工作,將數(shù)據(jù)成員初始化

創(chuàng)建對(duì)象時(shí),其類的構(gòu)造函數(shù)確保:在用戶操作對(duì)象之前,系統(tǒng)保證初始化的進(jìn)行

建立對(duì)象,須有一個(gè)有意義的初始值

c++建立和初始化對(duì)象的過(guò)程專門由類的構(gòu)造函數(shù)來(lái)完成

構(gòu)造函數(shù)給對(duì)象分配空間和初始化

如果一個(gè)類沒(méi)有專門定義構(gòu)造函數(shù),那么c++僅創(chuàng)建對(duì)象而不做任何初始化

構(gòu)造方法滿足以下語(yǔ)法規(guī)則:

1 構(gòu)造方法與類名相同

2 沒(méi)有返回值類型

3方法實(shí)現(xiàn)主要為字段賦值

放在外部定義的構(gòu)造函數(shù),其函數(shù)名前要加上“類名::”

構(gòu)造函數(shù)另一個(gè)特殊之處是他么有返回類型,函數(shù)體中也不允許返回值,但可以有無(wú)值返回語(yǔ)句“return”

因?yàn)闃?gòu)造函數(shù)專門用于創(chuàng)建對(duì)象和為其初始化,所以他是在定義對(duì)象時(shí)自動(dòng)調(diào)用的

如果創(chuàng)建一個(gè)對(duì)象數(shù)組

car car[3];//構(gòu)造函數(shù)會(huì)被調(diào)用5次Car::car()

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

Car(intprice ,intcarNum );

Car::Car(intprice ,intcarNum ):price(price),carNum(carNum){};

構(gòu)造函數(shù)前加一個(gè)explisit可以避免隱式類型轉(zhuǎn)換

#include

using namespace std;

class Box

{

public :

Box(int h=10,int w=10,int len=10); //在聲明構(gòu)造函數(shù)時(shí)指定默認(rèn)參數(shù)

int volume( );

private :

int height;

int width;

int length;

};

Box::Box(int h,int w,int len) //在定義函數(shù)時(shí)可以不指定默認(rèn)參數(shù)

{

height=h;

width=w;

length=len;

}

int Box::volume( )

{

return (height*width*length);

}

int main( )

{

Box box1; //沒(méi)有給實(shí)參

cout<<"The volume of box1 is "<

Box box2(15); //只給定一個(gè)實(shí)參

cout<<"The volume of box2 is "<

Box box3(15,30); //只給定2個(gè)實(shí)參

cout<<"The volume of box3 is "<

Box box4(15,30,20); //給定3個(gè)實(shí)參

cout<<"The volume of box4 is "<

return 0;

}

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

一個(gè)類可能在構(gòu)造函數(shù)里分配資源,這些資源需要在對(duì)象不復(fù)存在以前被釋放

析構(gòu)函數(shù)也是特殊類型的成員,它沒(méi)有參數(shù),不能隨意調(diào)用,也不能重載。只是在類對(duì)象生周期結(jié)束的時(shí)候由系統(tǒng)自動(dòng)調(diào)用

析構(gòu)函數(shù)名,就在構(gòu)造函數(shù)名之前加上一個(gè)邏輯非~運(yùn)算符即可,表示逆構(gòu)造函數(shù)。

同樣道理,只有在用戶沒(méi)有定義析構(gòu)函數(shù)的時(shí)候才會(huì)系統(tǒng)默認(rèn)創(chuàng)建一個(gè)構(gòu)造函數(shù)

對(duì)象在初始化時(shí)被分配內(nèi)存空間,調(diào)用構(gòu)造函數(shù)進(jìn)行初始化,在對(duì)象生命周期結(jié)束時(shí),銷毀對(duì)象,調(diào)用析構(gòu)函數(shù)釋放對(duì)象所占用的空間。對(duì)象的生命周期時(shí)候從他定義時(shí)算起,到到出了對(duì)象所在大括號(hào)時(shí)結(jié)束。

實(shí)例化對(duì)象

{

Carcar3(100,20);

}

對(duì)象的析構(gòu)函數(shù)

Car:: ~Car(){

cout<price<<endl;

cout<<"xi gou"<<endl;

};

//對(duì)象在釋放之前會(huì)調(diào)用這個(gè)函數(shù),你可以在對(duì)象釋放前做一些相應(yīng)的操作

標(biāo)準(zhǔn)庫(kù)類型string

中文的字符編碼中GB8030,漢子占兩個(gè)字節(jié)

string類型支持長(zhǎng)度可變的字符串

c++標(biāo)準(zhǔn)庫(kù)負(fù)責(zé)管理與存儲(chǔ)字符串所占用的內(nèi)存(#include <string> using namespace std;)

string 初始化方法


第三天?

static 靜態(tài)變量,靜態(tài)成員變量,靜態(tài)成員函數(shù)

參考地址:http://blog.csdn.net/kerry0071/article/details/25741425/

一 面向過(guò)程設(shè)計(jì)中的static關(guān)鍵字

1 靜態(tài)全局變量

定義:在全局變量前加上關(guān)鍵字static,該變量就被定義成一個(gè)靜態(tài)全局變量

特點(diǎn):

1)該變量在全局?jǐn)?shù)據(jù)區(qū)內(nèi)分配內(nèi)存

2)初始化:如果不顯示初始化,那么將被隱式初始化為0.(自動(dòng)變量是隨機(jī)的,除非是顯示初始化)

3)該變量只在本源文件可見,嚴(yán)格講,應(yīng)該從定義之處開始到本文件結(jié)束

注意:

在一個(gè)文件中定義了一個(gè)全局變量,在另外一個(gè)文件中只需要加一個(gè)extern即可訪問(wèn),而如果加上一個(gè)static關(guān)鍵字的話就只能在定義這個(gè)變量的文件中才能使用

靜態(tài)變量都在全局?jǐn)?shù)據(jù)區(qū)分配內(nèi)存,包括靜態(tài)局部變量。對(duì)于一個(gè)完整的程序,在內(nèi)存中分布情況如下:

代碼區(qū)

全局?jǐn)?shù)據(jù)區(qū)

堆區(qū)

棧區(qū)

一般在程序中,由new產(chǎn)生的動(dòng)態(tài)數(shù)據(jù)放在堆區(qū)中,函數(shù)內(nèi)部的自動(dòng)變量存放在棧區(qū)自動(dòng)變量會(huì)隨著函數(shù)的退出而釋放空間,靜態(tài)數(shù)據(jù)(即使是函數(shù)nebula的靜態(tài)局部變量)也會(huì)存放在全局?jǐn)?shù)據(jù)區(qū)中,全局?jǐn)?shù)據(jù)區(qū)的數(shù)據(jù)并不會(huì)因?yàn)楹瘮?shù)的退出而釋放空間。

2 靜態(tài)函數(shù)與普通函數(shù)不同,靜態(tài)函數(shù)只能在聲明他的文件當(dāng)中可見,不能被其他文件使用

二 面向?qū)ο蟪绦蛟O(shè)計(jì)中的static關(guān)鍵字

1.靜態(tài)數(shù)據(jù)成員

在類內(nèi)數(shù)據(jù)成員的聲明前加上static關(guān)鍵字,該數(shù)據(jù)成員就是類內(nèi)的靜態(tài)數(shù)據(jù)成員。

對(duì)非靜態(tài)成員數(shù)據(jù)成員,每個(gè)對(duì)象都有自己的拷貝,而靜態(tài)數(shù)據(jù)成員 被當(dāng)做是類的成員,無(wú)論這個(gè)類對(duì)象被定義了多少個(gè)對(duì)象,靜態(tài)數(shù)據(jù)成員在程序內(nèi)都只有一份拷貝,由該類型的所有對(duì)象共享訪問(wèn)。即靜態(tài)成員變量是所有的對(duì)象共用的,對(duì)該類的多個(gè)對(duì)象來(lái)說(shuō),靜態(tài)數(shù)據(jù)成員只分配一次內(nèi)存,供所有成員使用。

總結(jié):

說(shuō)白了,靜態(tài)數(shù)據(jù)成員的話就是說(shuō),首先它是一個(gè)存儲(chǔ)在全局區(qū)的變量,在程序編譯時(shí)分配空間,它不依賴于具體存在的對(duì)象而存在,它是屬于類本身的。因此可以在未實(shí)例化對(duì)象時(shí),直接通過(guò)類名進(jìn)行調(diào)用,對(duì)靜態(tài)成員變量進(jìn)行訪問(wèn)。當(dāng)然,這個(gè)成員變量是類的數(shù)據(jù)成員,每一個(gè)類的實(shí)例化對(duì)象都保留了對(duì)該對(duì)象的拷貝。雖然每個(gè)對(duì)象都保留了一份數(shù)據(jù)成員的拷貝,但由于成員變量的訪問(wèn)類型有public,protect,private三種,只有public和protect才可以被類的實(shí)例訪問(wèn)到,若將成員變量申明為private的話就只能在類內(nèi)部訪問(wèn),無(wú)論是類的實(shí)例化對(duì)象還是類本省都無(wú)法訪問(wèn)到private類型對(duì)象。只能通過(guò)定義接口開可以對(duì)靜態(tài)私有成員變量進(jìn)行訪問(wèn)。

靜態(tài)變量的優(yōu)勢(shì):

個(gè)人感覺(jué)靜態(tài)變量的優(yōu)勢(shì)在于,他只初始化一次,如果是共有的屬性的話將被所有的對(duì)象所共有,利于節(jié)省資源,同時(shí)利于對(duì)所有對(duì)象所共有屬性的管理。相比于全局變量的話,靜態(tài)數(shù)據(jù)成員具有3種訪問(wèn)屬性,可以實(shí)現(xiàn)信息的隱藏


靜態(tài)成員函數(shù)

靜態(tài)成員函數(shù)只能存在于類中,屬于是為整個(gè)類服務(wù)和靜態(tài)成員變量一樣。靜態(tài)成員函數(shù)只能訪問(wèn)靜態(tài)成員變量和靜態(tài)成員函數(shù)。

非靜態(tài)的成員函數(shù)可以訪問(wèn)靜態(tài)的成員函數(shù)和靜態(tài)成員

調(diào)用靜態(tài)成員函數(shù)可以使用成員操作符(.)和(->)為類的對(duì)象或指向類對(duì)象的指針條調(diào)用成員函數(shù)

總結(jié):

個(gè)人覺(jué)得吧,這個(gè)靜態(tài)成員函數(shù)也就是一個(gè)函數(shù),程序在編譯過(guò)后會(huì)存放在代碼區(qū)中,類也是代碼,所以按道理也會(huì)存在于代碼區(qū)中。通過(guò)類實(shí)例化對(duì)象的過(guò)程就是按照類的規(guī)則在堆區(qū)中開辟相應(yīng)的空間,成員函數(shù)名其實(shí)就是函數(shù)入口,你是這個(gè)類的實(shí)例對(duì)象那么你就可以調(diào)用這個(gè)成員函數(shù)(重要類允許你調(diào)用)。這也就是為什么一個(gè)實(shí)例對(duì)象可以調(diào)用類的靜態(tài)成員函數(shù)和普通成員函數(shù)的原因。


堆區(qū),棧區(qū),全局區(qū),文字常量區(qū),程序代碼區(qū)

1 棧區(qū)(stack)

由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。他的地址是從高到低逆序增長(zhǎng)

2 堆區(qū)(heap)

一般由程序員自己分配釋放,若程序員不釋放,程序結(jié)束時(shí)可能由os回收。

3 全局區(qū)(靜態(tài)區(qū))(static)

一,全局變量和靜態(tài)變量的存放是放在一塊兒的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的全局變量和為初始化的靜態(tài)變量在相鄰的另一塊區(qū)域,全局變量和靜態(tài)變量在程序結(jié)束后由系統(tǒng)釋放

4 文字常量區(qū)?

常量字符串就是放在這里的,程序結(jié)束后由系統(tǒng)釋放

5 代碼區(qū)?

存放函數(shù)體的二進(jìn)制代碼


第三天

動(dòng)態(tài)內(nèi)存分配


c 語(yǔ)言

malloc/free

c++

new/delete

c++的運(yùn)算符new/delete

在堆上生成對(duì)象,需要調(diào)用構(gòu)造函數(shù)

在堆上生成的對(duì)象,在釋放時(shí)需要自動(dòng)調(diào)用析構(gòu)函數(shù)

new/delete,malloc/free需要配對(duì)使用

new[]/delete[]生成和釋放對(duì)象數(shù)組也要配對(duì)使用

new/delete是運(yùn)算符,malloc/free是函數(shù)調(diào)用


小結(jié):

局部變量是存儲(chǔ)在棧上的,有擦操作系統(tǒng)管理局部變量的內(nèi)存。當(dāng)變量的生命周期結(jié)束后,由操作系統(tǒng)對(duì)變量的內(nèi)存進(jìn)行釋放。而使用new在堆上生成的對(duì)象就不一樣,堆上的對(duì)象必須要靠自己手動(dòng)來(lái)釋放空間才可以,你要是用了不釋放的話,對(duì)象將永遠(yuǎn)占用這部分空間(程序不停止)。在釋放了堆空間上的對(duì)象空間后,需要將對(duì)象指針指空,否則會(huì)造成野指針。

代碼存放在代碼區(qū),數(shù)據(jù)則根據(jù)類型的不同存放在不同的區(qū)域中

bss段存放沒(méi)有初始化或者初始化全為0 的全局變量(沒(méi)有初始化的全局變量和沒(méi)有初始化的靜態(tài)變量在內(nèi)存中的位置相同)

大多數(shù)的操作系統(tǒng)在加載程序的時(shí)候會(huì)把bss全局變量清零。為保證程序的可移植性,最好把變量的初始值初始化為0;

在程序運(yùn)行周期內(nèi),bss數(shù)據(jù)一直都存在

data段存放初始化為非0的全局變量

僅僅是將初始化值改為非0,文件的size就變大

同樣作為全局變量在整個(gè)運(yùn)行周期內(nèi),data數(shù)據(jù)一直存在

靜態(tài)成員變量在第一次進(jìn)入作用域時(shí)被初始化,以后不必再初始化

靜態(tài)成員變量可以在類之間共享數(shù)據(jù),也是放在全局/靜態(tài)數(shù)據(jù)區(qū)中。并且只有一份拷貝


常量數(shù)據(jù)區(qū)(rodata)

rodata存放常量數(shù)據(jù)

常量不一定要放在常量數(shù)據(jù)區(qū)中,有些立即數(shù)和指令編碼在一起,放在text中

字符串常量,編譯器會(huì)去掉重復(fù)的字符串,保證只有一個(gè)副本

常量是不能修改的

字符串會(huì)被編譯器自動(dòng)放到rodata中,加const關(guān)鍵字修飾的全局變量也放在常量數(shù)據(jù)區(qū)中


棧中存儲(chǔ)自動(dòng)名變量或者局部變量,以及傳遞的參數(shù)等

在函數(shù)內(nèi)部定義了一個(gè)變量,或者向函數(shù)傳遞參數(shù)時(shí),這些變量存儲(chǔ)在棧上,當(dāng)變量退出這些變量的作用域時(shí),這些棧上的存儲(chǔ)單元會(huì)被自動(dòng)釋放

堆是用戶程序控制的存儲(chǔ)區(qū),存儲(chǔ)動(dòng)態(tài)生成的數(shù)據(jù)

當(dāng)用malloc/new來(lái)申請(qǐng)一塊內(nèi)存或者創(chuàng)建一個(gè)對(duì)象是,申請(qǐng)的內(nèi)存是在堆上分配,需要記錄得到的地址,并在不需要的時(shí)候釋放這些內(nèi)存

棧內(nèi)存一般很小,滿足不了程序邏輯的要求

對(duì)象的生命周期是指對(duì)象從創(chuàng)建到被銷毀的過(guò)程,創(chuàng)建對(duì)象要占用一定的內(nèi)存,因此整個(gè)程序占用的內(nèi)存隨著對(duì)象的創(chuàng)建和銷毀動(dòng)態(tài)地發(fā)生變化。

變量的作用域決定了對(duì)象的生命周期

全局變量在mian之前被創(chuàng)建,main之后會(huì)被銷毀

靜態(tài)對(duì)象和全局對(duì)象類似,第一次進(jìn)入作用域被創(chuàng)建,但是程序開始時(shí),內(nèi)存已經(jīng)分配好

作用域由{}定義,并不是整個(gè)函數(shù)

通過(guò)new創(chuàng)建對(duì)象,很容易造成內(nèi)存泄露。通過(guò)new創(chuàng)建的對(duì)象一直存在,知道被delete銷毀

隱藏在中間的臨時(shí)變量的創(chuàng)建和銷毀,生命周期很短,容易造成問(wèn)題。

拷貝構(gòu)造函數(shù)

拷貝構(gòu)造函數(shù)是一種特殊的構(gòu)造函數(shù),具有單個(gè)形參,此形參是對(duì)該類型的引用。當(dāng)定義一個(gè)新對(duì)象并用同一個(gè)類型的對(duì)象對(duì)它進(jìn)行初始化時(shí),將顯示使用拷貝構(gòu)造函數(shù)

當(dāng)將該類型的對(duì)象傳遞給函數(shù)或從函數(shù)返回該類型的對(duì)象時(shí),將隱式調(diào)用拷貝構(gòu)造函數(shù)

如果一個(gè)類沒(méi)有定義拷貝構(gòu)造函數(shù),編譯器會(huì)默認(rèn)提供拷貝構(gòu)造函數(shù)

編譯器提供的默認(rèn)拷貝函數(shù)的行為

執(zhí)行逐個(gè)成員初始化,將新對(duì)象初始化為原對(duì)象的副本

逐個(gè)成員指的是編譯器將現(xiàn)有對(duì)象的每個(gè)非static成員依次復(fù)制到正在創(chuàng)建的對(duì)象

深拷貝和淺拷貝

參考:http://blog.csdn.net/lwbeyond/article/details/6202256/#

未重寫拷貝構(gòu)造函數(shù)時(shí)

重寫了拷貝構(gòu)造函數(shù)時(shí)


寫的不好



注意:你在構(gòu)造函數(shù)中在堆上申請(qǐng)了一段空間,那么在相應(yīng)的析構(gòu)函數(shù)中就要釋放這段空間


總結(jié):

現(xiàn)在來(lái)做一個(gè)總結(jié),首先來(lái)說(shuō)類是什么。

類是對(duì)客觀事物的抽象,是生成具體事物的模板。類就是一段代碼。

類的成員變量和成員函數(shù)具有private,peotrect,public三種類型。依次對(duì)應(yīng)著不同的訪問(wèn)權(quán)限。

通過(guò)類實(shí)例化一個(gè)對(duì)象的具體步驟:

1.通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象,系統(tǒng)提供默認(rèn)的構(gòu)造函數(shù),也可以重寫構(gòu)造函數(shù)。在構(gòu)造方法中可以直接對(duì)屬性進(jìn)行賦值,也可以使用初始化列表進(jìn)行賦值。

2.使用拷貝構(gòu)造函數(shù)對(duì)對(duì)象進(jìn)行賦值。同樣,系統(tǒng)提供了默認(rèn)的拷貝構(gòu)造函數(shù),但系統(tǒng)提供的默認(rèn)拷貝函數(shù)只是簡(jiǎn)單的進(jìn)行值拷貝,對(duì)于指針類的對(duì)象會(huì)造成兩個(gè)對(duì)象的同一個(gè)指針屬性指向同一塊內(nèi)存的問(wèn)題,最終在調(diào)用析構(gòu)函數(shù)釋放對(duì)象申請(qǐng)的空間時(shí)會(huì)造成多次同時(shí)釋放同一塊內(nèi)存的問(wèn)題,導(dǎo)致程序崩潰。這就是淺拷貝的問(wèn)題。解決淺拷貝的問(wèn)題是在拷貝構(gòu)造函數(shù)中對(duì)于指針變量指向的空間進(jìn)行重新分配,而不只是進(jìn)行簡(jiǎn)單的賦值。也就實(shí)現(xiàn)了對(duì)象的深拷貝。

對(duì)于用等號(hào)進(jìn)行賦值的對(duì)象,其實(shí)是對(duì)等號(hào)運(yùn)算符進(jìn)行了重載,并返回自身。

3.等號(hào)賦值一般先判斷是否是自身賦值給自身,若是自身給自身賦值,則直接返回*this即可。如不是自身給自身賦值,則先看被賦值對(duì)象的成員變變量是否是空,如不為空的話先釋放成員變量的原有空間,并將指針指空,接著判斷賦值對(duì)象的相關(guān)成員變量是否為空,若不為空則申請(qǐng)相同大小的空間,將相關(guān)成員變量的具體值復(fù)制即可。最后返回自己*this。本身。

個(gè)人覺(jué)得搞清楚什么時(shí)候調(diào)用拷貝構(gòu)造函數(shù),什么時(shí)候調(diào)用構(gòu)造函數(shù),什么時(shí)候是運(yùn)算符重載(等號(hào))非常重要


const關(guān)鍵字

const int buffer = 10;//編譯器看得到的

define的話僅僅是替換,屬于宏

const指定一個(gè)不該被改動(dòng)的對(duì)象

const int * p = &a;//這里的話const修飾的是*p,因此指針?biāo)赶虻膬?nèi)存區(qū)域內(nèi)的值不可修改

但可以給指針變量p賦新值。

int const *p = &a//這里const修飾的*p,也就說(shuō),這是個(gè)常量指針,指針的值不可變,但指針?biāo)赶虻膬?nèi)存空間的值可變

const數(shù)據(jù)成員必須使用成員初始化列表進(jìn)行初始化

const成員函數(shù)

類接口清晰,確定哪些函數(shù)可以修改數(shù)據(jù)成員




友元函數(shù)和友元類

在某些情況下,允許特定的非成員函數(shù)訪問(wèn)一個(gè)類的私有成員,同時(shí)阻止一般訪問(wèn)

友元機(jī)制允許一個(gè)類將其非公有成員的訪問(wèn)權(quán)限授予指定的函數(shù)或類

友元的聲明以關(guān)鍵字friend開始

只能出現(xiàn)在類定義的內(nèi)部

可以出現(xiàn)在類中的任何地方,不是授予友元關(guān)系的那個(gè)類成員,所以不受其聲明出現(xiàn)部分的訪問(wèn)控制影響


單例模式

單例模式的好處在于,可以控制生成對(duì)象的數(shù)量。

他的原理在于,將類的構(gòu)造函數(shù)定義為私有的,也就是說(shuō),外界不能調(diào)用類的構(gòu)造函數(shù)構(gòu)造類對(duì)象。提供一個(gè)靜態(tài)的成員函數(shù),通過(guò)這個(gè)靜態(tài)成員函數(shù)返回一個(gè)單例對(duì)象即可,彈藥主語(yǔ)的是你所返回的這個(gè)單例模式的對(duì)象必須要是類的私有靜態(tài)對(duì)象才行,因?yàn)殪o態(tài)成員函數(shù)只能訪問(wèn)靜態(tài)變量,靜態(tài)成員函數(shù)沒(méi)有this指針,所以不能訪問(wèn)普通成員變量和普通成員函數(shù)。另外類的靜態(tài)成員變量必須要在類的實(shí)現(xiàn)中進(jìn)行賦值,這也從另一方面證明了靜態(tài)成員變量是屬于類本身的說(shuō)法。

單例可以用來(lái)作為數(shù)據(jù)傳遞的工具







++,--自增自減運(yùn)算



自定義string 類型實(shí)現(xiàn)

?

重載+=?




其實(shí)還是改不了的,因?yàn)檫@是一個(gè)常量啊,感覺(jué)這就是一個(gè)建議而已,為了使得程序更好理解.這里的字符串是只讀的


繼承

基于已存在的類來(lái)構(gòu)建新類,當(dāng)從已存在的類繼承時(shí),就重用了它的方法和成員,還可以添加新的方法和成員來(lái)定制新的類以應(yīng)對(duì)需求

約定:從其他類導(dǎo)出的類叫子類,被導(dǎo)出的類叫父類

is -a繼承體現(xiàn)

has-a組合體現(xiàn)

繼承的意義:

代碼重用

體現(xiàn)不同抽象層次

父子類關(guān)系:

父類更抽象,跟一般

子類更具體,更特殊

UML 統(tǒng)一建模語(yǔ)言



類是一種抽象的數(shù)據(jù)類型,是實(shí)例化對(duì)象的模板

多繼承

多繼承的優(yōu)點(diǎn)是能夠獲得更多的父類屬性,靈活性高

缺點(diǎn)是屬性的二義性和數(shù)據(jù)的冗余

解決方式:

虛繼承,即當(dāng)類執(zhí)行繼承時(shí)只保留一份基類的數(shù)據(jù)

oc里面有個(gè)東西叫做協(xié)議,用協(xié)議的話也可以實(shí)現(xiàn)多繼承的效果,然而協(xié)議更加的高效,只要類與一個(gè)協(xié)議類型的對(duì)象,那么任何一個(gè)對(duì)象只要實(shí)現(xiàn)了協(xié)議,都可以為該屬性賦值,實(shí)現(xiàn)相應(yīng)的功能。

注意,通過(guò)指向基類的指針只能訪問(wèn)派生類中的基類成員,而不能訪問(wèn)派生類心增加的成員。

若想要通過(guò)基類的指針訪問(wèn)子類的屬性成員需要用到虛函數(shù)和指針。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第一章 計(jì)算機(jī)與C++編程簡(jiǎn)介 C++程序6個(gè)階段編程 ->預(yù)處理->編譯->連接->裝入->執(zhí)行1.程序在編譯器...
    rogertan30閱讀 4,513評(píng)論 0 1
  • hh哈哈哈哈哈哈哈哈哈
    yyyyyyhhhhhh閱讀 196評(píng)論 0 0
  • 1、JavaScript由瀏覽器解釋執(zhí)行。必須通過(guò)HTML/XHTML文檔才能執(zhí)行。 2、語(yǔ)法-2.1 語(yǔ)句推薦做...
    Nancy_01閱讀 343評(píng)論 0 1
  • 為進(jìn)一步提升分局干部職工業(yè)務(wù)素質(zhì)和操作技能,10月20日上午,大瑤分局遵循“抓業(yè)務(wù)、補(bǔ)短板”的工作思路,組織全體稅...
    旺老虎閱讀 557評(píng)論 0 3
  • 我正在認(rèn)識(shí)自己內(nèi)心的不足 我正在遇見更好的自己的路上 路上遇見很多小伙伴 我也開始接受新的事物 今日任務(wù)清單打卡 ...
    悅洋行者閱讀 336評(píng)論 0 0

友情鏈接更多精彩內(nèi)容