- enum 枚舉
enum spectrum{red, orange, yellow, green, blue, violet, indigo, ultraviolet};
spectrum band;
band = blue; - 指針
int * pt = new int;
delete pt;
new的用武之地:創(chuàng)建動態(tài)數(shù)組
int* psome = new int[10]
delete [] psome; 方括號告訴程序莹桅,應(yīng)釋放整個數(shù)組祈秕,而不僅僅是指針指向的元素。
指向數(shù)組的指針:
不同的C++存儲方式是通過存儲持續(xù)性、作用域和鏈接性來描述的酒请。
C++使用三種(C++11種是4種)不同的方案來存儲數(shù)據(jù)费尽,這些方案的區(qū)別是數(shù)據(jù)保留在內(nèi)存中的時間:
-
自動存儲持續(xù)性
存儲在棧中(后進(jìn)先出LIFO) 執(zhí)行代碼塊時帽撑,其中的變量依次加入到棧中褒搔,在離開代碼塊時脸甘,按相反的順序釋放這些變量恳啥。
在函數(shù)中定義聲明的變量(包括函數(shù)參數(shù))的存儲持續(xù)性都是自動的,它們在程序開始執(zhí)行其所屬的函數(shù)或代碼塊時被創(chuàng)建丹诀,在執(zhí)行完函數(shù)或代碼塊時钝的,它們使用的內(nèi)存被釋放。 -
靜態(tài)存儲
整個程序執(zhí)行期間都存在的存儲方式铆遭。兩種定義方式:在函數(shù)外面定義或者使用static硝桩。 -
動態(tài)存儲 自由存儲(free store)/堆(heap)
new delete
用new運(yùn)算符分配的內(nèi)存將一直存在,直到使用delete運(yùn)算符將其釋放或程序結(jié)束為止枚荣。 -
線程存儲持續(xù)性
如果變量使用thread_local聲明碗脊,則讓其聲明周期與所屬的線程一樣長。
作用域和鏈接
作用域:描述名稱在文件(單元)的多大范圍可見
鏈接性:描述了名稱如何在不同單元中共享
鏈接性在外部的名稱可在文件間共享
鏈接性為內(nèi)部的名稱只能由一個文件中的函數(shù)共享
自動變量沒有鏈接性橄妆,因?yàn)樗鼈儾荒芄蚕?/p>
- 默認(rèn)情況下衙伶,在函數(shù)中聲明的函數(shù)參數(shù)和變量的存儲持續(xù)性為自動,作用于為局部害碾,沒有鏈接性矢劲。
- 靜態(tài)存儲的鏈接性有3種:
外部鏈接性(可在其它文件中訪問)在外部聲明
int global = 1000;//static duration, external linkage
內(nèi)部鏈接性(只能在當(dāng)前文件中訪問)
在代碼塊外面聲明,并且使用static限定符蛮原。
無鏈接性(只能在當(dāng)前函數(shù)或代碼塊中訪問)
在代碼塊內(nèi)聲明卧须,并且使用static限定符
存儲描述 | 持續(xù)性 | 作用域 | 鏈接性 | 如何聲明 |
---|---|---|---|---|
自動 | 自動 | 代碼塊 | 無鏈接性 | 在代碼塊中 |
存儲器 | 自動 | 代碼塊 | 無鏈接性 | 在代碼塊中另绩,使用關(guān)鍵字register |
靜態(tài)儒陨,無鏈接性 | 靜態(tài) | 代碼塊 | 無鏈接性 | 在代碼塊中,使用關(guān)鍵字static |
靜態(tài)笋籽,外部鏈接性 | 靜態(tài) | 文件 | 外部鏈接性 | 不在任何函數(shù)內(nèi) |
靜態(tài)蹦漠,內(nèi)部鏈接性 | 靜態(tài) | 文件 | 內(nèi)部連接性 | 不在任何函數(shù)內(nèi),使用關(guān)鍵字static |
由于靜態(tài)變量的數(shù)目在程序運(yùn)行期間是不變的车海,因此程序不需要使用特殊的裝置(如棧)來管理它們笛园。編譯器將分配固定的內(nèi)存塊來存儲所有的靜態(tài)變量。
靜態(tài)持續(xù)性侍芝,外部鏈接性
鏈接性為外部的變量通常簡稱為外部變量研铆,外部變量也稱全局變量
單定義規(guī)則:
在每個使用外部變量的文件中,都必須聲明它州叠,
定義聲明:defining declaration 簡稱定義
引用聲明棵红,reference declaration 簡稱聲明
引用聲明使用關(guān)鍵字 extern
//file01.cpp
extern int cats = 20;
int dogs = 22;
int fleas;
//file02.cpp
extern int cats;
extern int dogs;
//file03.cpp
extern int cats;
extern int dogs;
extern int fleas;
作用域解釋符(::),放在變量名前面時咧栗,該運(yùn)算符表示使用變量的全局版本逆甜。
可以使用外部變量在多文件程序的不同部分之間共享數(shù)據(jù)虱肄;可以使用鏈接性為內(nèi)部的靜態(tài)變量在同一個文件中的多個函數(shù)之間共享數(shù)據(jù)(名稱空間提供了另外一種數(shù)據(jù)共享的方法)。如果將作用域?yàn)檎麄€文件的變量變?yōu)殪o態(tài)的交煞,就不必?fù)?dān)心其名稱與其他文件中的作用域?yàn)檎麄€文件的變量發(fā)生沖突
-
存儲說明符 CV限定符
存儲說明符:auto register static extern thread_local mutable
CV限定符 const(內(nèi)存被初始化后咏窿,程序便不能對它再進(jìn)行修改)
volatile(即使程序代碼沒有對內(nèi)存單元進(jìn)行修改,其值也可能發(fā)生變化素征。告訴編譯器集嵌,不要進(jìn)行這種優(yōu)化)
mutable:即使結(jié)構(gòu)(或類)變量為const,其某個成員也可以被修改御毅。
struct data
{
char name[30];
mutable int accesses;
}
const data veep={"Claybourne Clodde",0,...};
strcpy(veep.name,"Joye Joux");//not allowed
veep.accesses++;
在C++中纸淮,const對默認(rèn)存儲類型稍有影響。在默認(rèn)情況下全局變量的鏈接性為外部亚享。但const全局變量的連接性為內(nèi)部咽块。也就是說,在C++看來欺税,全局const定義就像使用了static說明符一樣
- 將一組常量放在頭文件中
函數(shù)和鏈接性
所用函數(shù)的存儲持續(xù)性都是靜態(tài)的侈沪,即在整個程序執(zhí)行期間都一直存在。默認(rèn)情況下晚凿,函數(shù)的鏈接性為外部亭罪,即可以在文件間共享,可以在函數(shù)原型中使用關(guān)鍵字extern來指出函數(shù)是在另一個文件中定義的(但這是可選的)
還可以使用關(guān)鍵字static將函數(shù)的鏈接性設(shè)置為內(nèi)部的歼秽,使之只能在一個文件中使用应役,必須同時在原型和函數(shù)定義中使用關(guān)鍵字static。
語言鏈接性(c++ language linkage)
鏈接程序要求每個不同的函數(shù)都有不同的符號名燥筷,在C語言中箩祥,一個名稱只對應(yīng)一個函數(shù)。但是C++中肆氓,一個名稱可能對應(yīng)多一個函數(shù)袍祖。必須將這些函數(shù)翻譯為不同的符號名稱,因此C++編譯器執(zhí)行名稱矯正或名稱修飾谢揪,為重載函數(shù)生成不同的符號名稱蕉陋。鏈接程序在尋找于C++函數(shù)調(diào)用的匹配的函數(shù)時,使用的方法與C語言不同拨扶,但如果要在C++程序中使用C庫預(yù)編譯的函數(shù)凳鬓,可以用函數(shù)原型來指出要使用的約定:
extern "C" void spiff(int); //use C protocal for name look-up
extern void spoff(int);//use C++ protocal for name look-up
extern "C++" void spaff(int);//use C++ protocal for name look-up
存儲方案和動態(tài)分配
前面的幾種內(nèi)存分配方案不使用與C++運(yùn)算符new(或C函數(shù)malloc)分配的內(nèi)存,這種內(nèi)存被稱為動態(tài)內(nèi)存患民,動態(tài)內(nèi)存由new和delete控制缩举,而不是由作用域和鏈接性規(guī)則控制。與自動內(nèi)存不同,動態(tài)內(nèi)存不是LIFO蚁孔,其分配和釋放順序要取決于new和delete在何時以何種方式被使用奶赔。
編譯器使用三塊獨(dú)立的內(nèi)存:一塊用于靜態(tài)變量,一塊用于自動變量杠氢,一塊用于動態(tài)存儲站刑。
存儲方案不適用于動態(tài)內(nèi)存,但使用與用來跟蹤動態(tài)內(nèi)存的自動和靜態(tài)指針變量鼻百。
使用new運(yùn)算符初始化:
int *pi = new int (6);
double * pd = new double(99.99);
struct where{double x;double y;double z;};
where *one = new where{2.5,5.3,7.2};
int * ar = new int[4]{2,3,6,7};
placement new
#include <new>
p1 = new chaff;//new a structure in heap
p1= new (buffer) chaff//new a structrure in the buffer
名稱空間
聲明區(qū)域(declaration region)可以在其中進(jìn)行聲明的區(qū)域
潛在作用域:從聲明點(diǎn)開始绞旅,到其聲明區(qū)域的結(jié)尾。
名稱空間可以是全局的温艇,也可以位于另一個名稱空間中因悲。但不能位于代碼塊中。在默認(rèn)情況下勺爱,在名稱空間中聲明的名稱的鏈接性為外部的(除非它引用了常量)
using聲明 指定特定的標(biāo)識符可用
using Jill::fetch;
main中的using聲明Jill::fetch將fetch添加到main()定義的聲明區(qū)域中晃琳。
在函數(shù)的外面使用using聲明時,將把名稱添加到全局名稱空間中琐鲁。
using編譯指令 使整個名稱空間可用
using namespace xxx ;
類
- 訪問控制
private public protected 描述了對類成員的訪問控制
使用類對象的程序都可以直接訪問共有部分卫旱。但只能通過共有函數(shù)(或者友元函數(shù))來訪問對象的私有成員。
防止程序直接訪問數(shù)據(jù)稱為數(shù)據(jù)隱藏
封裝:將實(shí)現(xiàn)細(xì)節(jié)放在一起围段,并且將它們與抽象分開
數(shù)據(jù)隱藏是一種封裝顾翼,將類函數(shù)定義和類聲明放在不同的文件中也是一種封裝 - 通常將數(shù)據(jù)放在私有部分,將類接口的成員函數(shù)放在共有部分奈泪。
類函數(shù)可以訪問類的private組件 - 內(nèi)聯(lián)函數(shù)
其定義位于類聲明中的函數(shù)都將自動成為內(nèi)聯(lián)函數(shù)
也可以在類聲明之外定義成員函數(shù)适贸,并使其成為內(nèi)聯(lián)函數(shù)。只需在類實(shí)現(xiàn)部分中定義函數(shù)時使用inline限定符即可 - 類的構(gòu)造函數(shù)和析構(gòu)函數(shù)
構(gòu)造函數(shù) 沒有返回值
Stock(const string & co, long n = 0 , double pr = 0.0);
成員函數(shù):
const Stock& topval(const Stock & s) const; - 對象數(shù)組
Stock mystuff[4];
···
const int STKS = 10;
Stock stocks[STKS] = {
Stock("NanoSmart",12.5,20);
Stock(),
Stock("Monolithic Obelisks",130,3.25);
}
···
初始化對象數(shù)組的方案:首先使用默認(rèn)構(gòu)造函數(shù)創(chuàng)建數(shù)組元素涝桅,然后花括號中的構(gòu)造函數(shù)將創(chuàng)建臨時對象拜姿,然后將臨時對象的內(nèi)容復(fù)制到相應(yīng)的元素中。要創(chuàng)建類對象數(shù)組苹支,則這個類必須有默認(rèn)構(gòu)造函數(shù) - 運(yùn)算符的重載:
Time operator+(cons Time & t) const;
total = coding.operator+(fixing);
total = coding + fixing; - 重載的限制:
1 重載后的運(yùn)算符必須至少有一個操作數(shù)是用戶定義的類型
2 不能將減法運(yùn)算符重載為計(jì)算兩個double值的和砾隅,而不是它們的差。
不能修改運(yùn)算符的優(yōu)先級
3 不能創(chuàng)建新的運(yùn)算符
4 不能重載下面的運(yùn)算符:
sizeof()
.
::
?:
typeid
const_cast dynamic_cast reinterpret_cast static_cast
5 表中大多數(shù)運(yùn)算符都可以通過成員函數(shù)或非成員函數(shù)進(jìn)行重載:但下面的運(yùn)算符只能通過成員函數(shù)進(jìn)行重載:
=
()
[]
->
Time Time::operator*(double mult) const
{
}
- 類的自動轉(zhuǎn)換與強(qiáng)制類型轉(zhuǎn)換
只有接收一個參數(shù)的構(gòu)造函數(shù)才能作為轉(zhuǎn)換函數(shù)
Stonewt(double lbs);
Stonewt mycat;
mycat = 19.6债蜜;
程序?qū)⑹褂脴?gòu)造函數(shù)Stonewt(double)來創(chuàng)建一個臨時的Stonewt對象,并將19.6作為初始化值究反。隨后寻定,采用逐成員賦值的方式將該臨時對象的內(nèi)容復(fù)制到mycat中。這一過程稱為隱式轉(zhuǎn)換精耐。
如果第二個參數(shù)提供默認(rèn)值狼速,它便可用于轉(zhuǎn)換int.
自動特性并非總是合乎需要的。因此卦停,C++新增了關(guān)鍵字explicit向胡,用于關(guān)閉這種自動特性:也就是說恼蓬,可以這樣聲明構(gòu)造函數(shù):
explicit Stonewt(double lbs)
這樣將關(guān)閉上述示例中介紹的隱式轉(zhuǎn)換,但仍然允許顯式轉(zhuǎn)換僵芹,即顯示強(qiáng)制類型轉(zhuǎn)換:
Stonewt mycat;
mycat = 19.6;//not valid if Stonewt(double) is declared as explicit
mycat = Stonewt(19.6);//ok, an explicit conversion
- 使用特殊的C++運(yùn)算符函數(shù)---轉(zhuǎn)換函數(shù)
轉(zhuǎn)換函數(shù)是用戶定義的強(qiáng)制類型轉(zhuǎn)換处硬,可以像使用強(qiáng)制類型轉(zhuǎn)換那樣使用它們。如果定義了Stonewt到double的轉(zhuǎn)換拇派,就可以使用下面的轉(zhuǎn)化:
Stonewt wolfe(285.7)
double host = wolfe;
//double host = double(wolfe)
operator typeName();
轉(zhuǎn)換函數(shù)必須是類方法荷辕,轉(zhuǎn)換函數(shù)不能指定返回類型,轉(zhuǎn)換函數(shù)不能有參數(shù),但是有返回值
operator double();
可以將轉(zhuǎn)換運(yùn)算符聲明為顯示的:
···
explicit operator int() const;
explicit operator double() const;
···
友元
-
友元函數(shù)
創(chuàng)建友元函數(shù)第一步是將其原型放在類聲明中件豌,并在類聲明前面加上關(guān)鍵字friend
friend Time operator*(double m, const Time & t);
//在定義中不要使用friend
- 常用的友元:重載<<運(yùn)算符 cout<<
ostream & operator<<(ostream & os, const Time & t)
{
os << t.hours << " hours" << t.minutes << "minutes";
return os;
}
cout << trip;
ofstream fout;
fout.open("savetime.txt");
Time trip(12,40);
fout << trip; //類的繼承屬性讓ostream引用能指向ostream和ofstream對象
友元類
友元成員函數(shù)
特殊成員函數(shù)
默認(rèn)構(gòu)造函數(shù)疮方,如果沒有定義構(gòu)造函數(shù)
如果定義了構(gòu)造函數(shù),C++將不會定義默認(rèn)構(gòu)造函數(shù)茧彤,如果希望在創(chuàng)建對象時不顯示地對它進(jìn)行初始化骡显,則必須顯示地定義默認(rèn)構(gòu)造函數(shù),這種構(gòu)造函數(shù)沒有任何參數(shù)
帶參數(shù)的構(gòu)造函數(shù)也可以時默認(rèn)構(gòu)造函數(shù)曾掂,只要所有參數(shù)都有默認(rèn)的值
默認(rèn)析構(gòu)函數(shù)蟆盐,如果沒有定義
復(fù)制構(gòu)造函數(shù),如果沒有定義
新建一個對象并將它初始化為同類現(xiàn)有對象時遭殉,復(fù)制構(gòu)造函數(shù)都將被調(diào)用
StringBad ditto(motto);
StringBad metto = motto;//
StringBad also = StringBad(motto);
//直接使用賦值構(gòu)造函數(shù)生成一個臨時對象石挂,然后將臨時對象的內(nèi)容賦給metoo和also
StringBad* pStringBad = new StringBad(motto);
//初始化一個匿名對象,然后把新對象的地址賦值給pstring指針
定義一個顯式復(fù)制構(gòu)造函數(shù)以解決問題:
進(jìn)行深度復(fù)制(復(fù)制構(gòu)造函數(shù)應(yīng)當(dāng)復(fù)制字符串并將副本的地址賦給str成員)
默認(rèn)構(gòu)造函數(shù)逐個復(fù)制非靜態(tài)成員(成員復(fù)制也稱為淺復(fù)制)险污,復(fù)制的是成員的值痹愚。
賦值運(yùn)算符,如果沒有定義
解決辦法:進(jìn)行深度復(fù)制
String::String(const String & st)
{
num_strings++;
len = st.len;
str = new char[len+1];
std::strcpy(str,st.str);
}
String & String::operator=(const String & st)
{
if(this == &st)
return *this;
delete [] str;
len = st.len;
str = new char[len+1];
std::strcpy(str,st.str);
return *this;
}
地址運(yùn)算符蛔糯,如果沒有定義
(c++11移動構(gòu)造函數(shù)
移動賦值運(yùn)算符)
- 靜態(tài)類成員函數(shù):
可以將成員函數(shù)聲明為靜態(tài)的(函數(shù)聲明包含關(guān)鍵字static)U!蚁飒!
不能通過對象調(diào)用靜態(tài)成員函數(shù)动壤,靜態(tài)成員函數(shù)甚至不能使用this指針。如果靜態(tài)成員函數(shù)是在公有部分聲明的淮逻,則可以使用類名和作用域解析運(yùn)算符來調(diào)用它琼懊。
其次,由于靜態(tài)成員函數(shù)不與特定的對象相關(guān)聯(lián)爬早。因此只能使用靜態(tài)成員數(shù)據(jù)哼丈。
可以重載賦值運(yùn)算符,使之能接收對象的銀行和直接使用常規(guī)字符串筛严。
成員初始化列表
繼承 --3種繼承關(guān)系(公有繼承醉旦,保護(hù)繼承,私有繼承)
公有繼承 is-a關(guān)系 (is-a-kind-of)
class RatedPlayer : public TableTennisPlayer
{
...
}
公有派生,派生類對象包含積累對象车胡。
使用公有派生檬输,基類的公有成員將稱為派生類的公有成員;基類的私有部分也將稱為派生類的一部分匈棘,但只能通過基類的公有和保護(hù)方法訪問丧慈。
派生類需要自己的構(gòu)造函數(shù)
派生類可以根據(jù)需要添加額外的數(shù)據(jù)成員和成員函數(shù)。
派生類構(gòu)造函數(shù)必須使用基類構(gòu)造函數(shù)
RatedPlayer::RatedPlayer(unsigned int r,const string & fn,
const string & ln, book ht) : TableTennisPlayer(fn, ln, ht)
{
rating = r;
}
- 有關(guān)派生類構(gòu)造函數(shù)的要點(diǎn)如下:
首先創(chuàng)建基類對象
派生類構(gòu)造函數(shù)應(yīng)通過成員初始化列表傳遞給基類構(gòu)造函數(shù)
派生類構(gòu)造函數(shù)應(yīng)初始化派生類新增的數(shù)據(jù)成員 - 派生類和基類的關(guān)系:
派生類對象可以使用基類的方法
基類指針可以在不進(jìn)行顯示類型轉(zhuǎn)換的情況下指向派生類對象羹饰∫磷蹋基類引用可以在不進(jìn)行顯示類型轉(zhuǎn)換的情況下引用派生類對象。
多態(tài)公有繼承
希望同一個方法在派生類和基類中的行為是不同的队秩。方法的行為取決于調(diào)用該方法的對象笑旺。這種較復(fù)雜的行為稱為多態(tài)--具有多種形態(tài)
有兩種機(jī)制可以實(shí)現(xiàn)多態(tài)的公有繼承:
在派生類中重新定義基類的方法
- 使用虛方法
//ViewAcct()不是虛函數(shù)
Brass dom("Dominic Banker",11224,4183.45);
BrassPlus dot("Dorothy Banker",12118,2592.00);
Brass & b1_ref = dom;
Brass & b2_ref = dot;
b1_ref.ViewAcct();//調(diào)用Brass的
b2_ref.ViewAcct();//調(diào)用Brass的
//使用虛函數(shù)
Brass dom("Dominic Banker",11224,4183.45);
BrassPlus dot("Dorothy Banker",12118,2592.00);
Brass & b1_ref = dom;
Brass & b2_ref = dot;
b1_ref.ViewAcct();//調(diào)用Brass的
b2_ref.ViewAcct();//調(diào)用BrassPlus
1 方法在基類聲明為虛后,它在派生類中將自動成為虛方法馍资。然而筒主,在派生類聲明中使用關(guān)鍵字virtual來指出哪些函數(shù)是虛函數(shù)也不失為一個好方法。
2 基類聲明一個虛析構(gòu)函數(shù)鸟蟹,這樣做確保釋放派生類對象時乌妙,按照正確的順序調(diào)用析構(gòu)函數(shù)。如果虛構(gòu)函數(shù)不是虛的建钥,則只調(diào)用對應(yīng)于指針類型的析構(gòu)函數(shù)藤韵。
Brass * p_clients[CLIENTS];
將派生類引用或指針轉(zhuǎn)換為基類引用或指針被稱為向上強(qiáng)制轉(zhuǎn)換,這使公有繼承不需要進(jìn)行顯示類型轉(zhuǎn)換熊经。
編譯器對非虛方法使用靜態(tài)聯(lián)編
對虛方法使用動態(tài)聯(lián)編
- 虛函數(shù)的工作原理
編譯器處理虛函數(shù)的方法:
給每個對象添加一個隱藏成員泽艘。隱藏成員中保存了一個指向函數(shù)地址數(shù)組的指針。這種數(shù)組稱為虛函數(shù)表(virtual function table, vtbl)镐依。虛函數(shù)表中存儲了為 類對象進(jìn)行聲明的虛函數(shù)地址匹涮。
調(diào)用虛函數(shù)時,程序?qū)⒉榭创鎯υ趯ο笾械膙tbl地址槐壳,然后轉(zhuǎn)向相應(yīng)的函數(shù)地址表然低。如果使用類聲明中定義的第一個虛函數(shù),則程序?qū)⑹褂脭?shù)組中的第一個函數(shù)地址务唐,并執(zhí)行具有該地址的函數(shù)雳攘。
overload(重載)相同函數(shù)名 不同參數(shù)
overwrite子類重寫父類方法
在派生類中重新定義函數(shù),將不是使用相同的函數(shù)特征標(biāo)覆蓋基類聲明绍哎,而是隱藏同名的基類方法来农,不管參數(shù)特征標(biāo)如何。
protected
派生類的成員可以直接訪問基類的保護(hù)成員崇堰,但不能直接訪問基類的私有成員
抽象基類
abstract base class, ABC
C++通過使用春虛函數(shù)提供未實(shí)現(xiàn)的函數(shù)。純虛函數(shù)聲明的結(jié)尾處為 =0
當(dāng)類聲明中包含純虛函數(shù)時,則不能創(chuàng)建該類的對象海诲。包含純虛函數(shù)的類只用作基類繁莹。純虛函數(shù)也可以有定義。
可以將ABC看作是一種必須實(shí)施的接口特幔,ABC要求具體派生類覆蓋其純虛函數(shù)--迫使派生類遵循ABC設(shè)置的接口規(guī)則咨演。
保護(hù)繼承
私有繼承
堆(heap)
- vector set
strlen返回字符串長度
指針
- 指針和const
第一種:讓指針指向一個常量對象,這樣可以防止使用該指針來修改所指向的值蚯斯。
int age = 39;
const int * pt = &age; 指針指向const int
不能通過pt來修改age的值薄风,但是可以通過age直接修改age的值,因?yàn)閍ge不是const拍嵌。
第二種:將指針本身聲明為常量遭赂,這樣可以防止改變指針指向的位置
int const * pt2 = &age; const指針
int * const pt2 = &age; - 函數(shù)指針
函數(shù)的地址:函數(shù)名
聲明函數(shù)指針:
double pam(int);//函數(shù)原型
double (*pf) (int);//指向函數(shù)的指針,1個int參數(shù)横辆,返回double撇他;
pf=pam; 讓函數(shù)指針指向函數(shù)
注意區(qū)分
double* pf (int) 和 double(pf)(int)
void estimate(int lines,double (pf) (int));//函數(shù)原型 第二個參數(shù)是一個函數(shù)指針
estimate(50,pam);
使用指針來調(diào)用函數(shù)
使用指針來調(diào)用被指向的函數(shù)。(pf)扮演的角色與函數(shù)名相同
double x = pam(4); //calling pam() using the function name
double y = (pf)(5);//calling pam() using the pointer pf
函數(shù)指針數(shù)組
const double* (*pa[3])(const double ,int) = {f1,f2,f3};
const double * px = (pa[0])(av,3);
double y = (pa[1])(av,3);
typedef const double (p_fun)(const double ,int);
p_fun p1 = f1; p1指向f1
p_fun pa[3] = {f1,f2,f3}狈蚤; pa是一個array of 3 function pointers
p_fun (pd)[3] = &pa; pd points to an array of 3 function pointers.
- 浮點(diǎn)數(shù)的寫法 科學(xué)計(jì)數(shù)法 10的幾次方
10e-6 - 表達(dá)式中的轉(zhuǎn)換
當(dāng)同一個表達(dá)式中包含兩種不同的算術(shù)類型時困肩,C++將執(zhí)行兩種轉(zhuǎn)換:
1 自動轉(zhuǎn)換
short chicken = 20;
short ducks = 35;
short fowl = chicken + ducks;
在執(zhí)行第三句的時候,程序把short先轉(zhuǎn)化為int進(jìn)行計(jì)算脆侮,然后將結(jié)果轉(zhuǎn)換為short.
2 整型提升
4種類型轉(zhuǎn)換
C++還引入了4個強(qiáng)制類型轉(zhuǎn)換運(yùn)算符
- dynamic_cast
- const_cast
- static_cast 將值從一種數(shù)值類轉(zhuǎn)換為另外一種數(shù)值類型
int thorn;
static_cast<long> (thorn)
static_cast<typeName> (value) - reinterpret_cast
函數(shù)
- 內(nèi)聯(lián)函數(shù)
在函數(shù)聲明前加上關(guān)鍵字inline
在函數(shù)定義前加上關(guān)鍵字inline - 引用變量
-
函數(shù)多態(tài)(函數(shù)重載)
同名函數(shù)锌畸,但是參數(shù)列表不同
多態(tài):多種形式 -
函數(shù)模板:(通用編程)//這種是函數(shù)多態(tài)的升級 上面的函數(shù)多態(tài)對不同類型的參數(shù)還需要逐個寫出來。模板就不用了靖避,直接替代
通用的函數(shù)描述
使用泛型來定義函數(shù)揩瞪,其中的泛型可用具體的類型替換桑逝。
template <typename AnyType> 建立一個模板 typename可以用class代替,template和typename是關(guān)鍵字 T來代替AnyType也是可以的
void Swap(AnyType &a, AnyType &b) 模板不會創(chuàng)建任何函數(shù)。當(dāng)需要交換int函數(shù)時戏蔑,編譯器將按模板模式創(chuàng)建這樣的函數(shù)
{
AnyType temp;
temp = a;
a = b;
b = temp;
} - 重載的模板
被重載的函數(shù)特征標(biāo)必須不同
template <typename T>
void Swap(T& a, T& b);
template <typename T>
void Swap(T *a, T *b,int n); - 為特定類型提供具體化的模板
顯示具體化(explicit specialization) 當(dāng)編譯器中找到與函數(shù)調(diào)用匹配的具體化定義時,將使用該定義而不再尋找模板汁政。
對于給第那個的函數(shù)名勉躺,可以有非模板函數(shù),模板函數(shù)和顯示具體化模板函數(shù)以及它們的重載版本
//not template function prototype
void Swap(job &, job &);
//template prototype
template<typename T>
void Swap(job &, job &);
template <> void Swap<job>(job&,job&);
template <> void Swap(job&,job&);//不要使用Swap模板來生成函數(shù)定義瓮下,而應(yīng)該使用專門為int類型顯式定義的函數(shù)定義
非模板版本>顯示具體化>模板生成的版本
函數(shù)調(diào)用Swap(i,j)導(dǎo)致編譯器生成Swap的一個實(shí)例翰铡,該實(shí)例使用int類型
隱式實(shí)例化(implicit instantiation),使用模板生成函數(shù)定義
顯示實(shí)例化(explicit instantiaion) 可以直接命令編譯器創(chuàng)建特定的實(shí)例
template void Swap<int>(int &,int &);//該聲明的意思是“使用Swap()模板生成int類型的函數(shù)定義”
隱式實(shí)例化讽坏,顯示實(shí)例化锭魔,顯示具體化統(tǒng)稱為具體化。相同之處:標(biāo)識的都是具體類型的函數(shù)定義路呜,而不是通用描述 - 編譯器使用哪個函數(shù)版本:
完全匹配(常規(guī)函數(shù)優(yōu)先于模板)
提升轉(zhuǎn)換(char/short -> int, long->double )
標(biāo)準(zhǔn)轉(zhuǎn)換(int -> char, long ->double)
用戶定義的轉(zhuǎn)換迷捧,如類聲明中定義的轉(zhuǎn)換织咧。 - 堆棧
中綴表達(dá)式
后綴表達(dá)式 求值策略:從左向右掃描,逐個處理運(yùn)算數(shù)和運(yùn)算符號
先放進(jìn)去后拿出來 堆棧
堆棧(stack)具有一定操作約束的線性表漠秋。只在一端(棧頂笙蒙,Top)做插入、刪除
插入數(shù)據(jù):入棧(Push)
刪除數(shù)據(jù):出棧(Pop)
后入先出:Last in First Out(LIFO)
放在桌子上的一疊碗
堆椙旖酰可以用來倒序輸出