第一天
一.內(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ù)和指針。