我們都知道C++其實(shí)就是C語(yǔ)言的升級(jí),那么在“升級(jí)”最初階段就是要對(duì)一些在C語(yǔ)言中不足的語(yǔ)法進(jìn)行改進(jìn),這些改進(jìn)能讓我們省很多的力并且代碼寫(xiě)起來(lái)也比較簡(jiǎn)潔。
一、命名空間
1、為什么要引入命名空間?
C++引入命名空間主要是為了彌補(bǔ)在C語(yǔ)言中不能存在同名變量或函數(shù)的這個(gè)語(yǔ)法漏洞。
我們知道在C語(yǔ)言中,相同名稱或變量是不能同時(shí)存在的:
如上面的例子中,編譯器就會(huì)報(bào)錯(cuò)。
2、命名空間的基本用法
為了解決這個(gè)問(wèn)題,C++就引入了命名空間,命名空間的主要語(yǔ)法如下:
namespace _name {
// 成員
int a = 1;
// 成員
double b = 1.1;
}
命名空間使用,namespace這個(gè)關(guān)鍵自定義,在命名空間中我們可以定義各種成員,我們幾乎可以定義所有的東西:變量、函數(shù)、結(jié)構(gòu)體(類)、命名空間(嵌套定義)……
而當(dāng)我們要在命名空間外使用這些成員時(shí),我就必須得加上一個(gè)“域作用限定符”:
_name::
而如果不加上,就會(huì)報(bào)錯(cuò):
這是因?yàn)镃++的編譯器也和C語(yǔ)言的編譯器一樣默認(rèn)只會(huì)在全局去尋找。
這樣我們就可以同時(shí)定義兩個(gè)同名函數(shù)了,比如在全局也有一個(gè)同名的Add函數(shù):
3、展開(kāi)命名空間
而如果我們不想每次使用都要加上與作用限定符或者某一個(gè)成員被使用的次數(shù)太過(guò)頻繁,我們就可以將命名空間進(jìn)行展開(kāi):
全部展開(kāi)
using namespace _name;
當(dāng)然,當(dāng)我們展命名空間后,也是不能存在同名函數(shù)的,因?yàn)榫幾g器會(huì)依次在全局和命名空間中查找,如果找到兩個(gè)同名函數(shù),就會(huì)存在歧義:
上面展示的是將命名空間全部展開(kāi),而如果我們只是經(jīng)常要用到命名空間中的某一個(gè)成員,而并不想展開(kāi)其他成員,那我們就可以使用部分展開(kāi)
using _name::Add;
而對(duì)其他成員,我們依然要加上域作用限定符:
4、命名空間的套娃
在命名空間中也是可以再定義命名空間的:
這樣,我們就可以再定義很多的同名變量和函數(shù)了。
在使用的時(shí)候其實(shí)也和C語(yǔ)言的指針解引用一樣,再加上一個(gè)域作用限定符就行了:
理論上我們可以嵌套無(wú)數(shù)層的命名空間,但在實(shí)際應(yīng)用中我們最多就嵌套兩層就足夠了。
5、命名空間的自動(dòng)合并
那么問(wèn)題來(lái)了,如果定義了同名的命名空間編譯器會(huì)不會(huì)報(bào)錯(cuò)呢?
答案是不會(huì)的,當(dāng)我們定義了多個(gè)命名空間,它們會(huì)自動(dòng)合并:
二、缺省參數(shù)
1、為什么要引入缺省參數(shù)?
在C語(yǔ)言中,當(dāng)我們要對(duì)完成某些功能的函數(shù),進(jìn)行傳參時(shí),總是會(huì)遇到不知道具體參數(shù)要傳多少的情況,比如我們要寫(xiě)一個(gè)棧,我們想要在初始化接口中給棧分配一個(gè)空間,因?yàn)閳?chǎng)景的不同,我們總不能具體知道要分配多少空間:
typedef struct Stack {
int* array;
int size;
int capacity;
} Stack;
void StackInit(Stack* pst) {
assert(pst);
pst->array = (int*)malloc((? ) * sizeof(int));
if (NULL == pst->array) {
perror("malloc fail!\n");
exit(-1);
}
pst->size = 0;
pst->capacity = ? ;
}
針對(duì)這種情況,C++就引入了缺省參數(shù)來(lái)解決。
2、缺省參數(shù)的基本用法
缺省參數(shù)就是在函數(shù)定義時(shí),在形參部分給一個(gè)“缺省值”:
void StackInit(Stack* pst, int n = 4) {
assert(pst);
pst->array = (int*)malloc((?n) * sizeof(int));
if (NULL == pst->array) {
perror("malloc fail!\n");
exit(-1);
}
pst->size = 0;
pst->capacity = n ;
}
當(dāng)我們使用時(shí),可以顯示給值或者不顯示給值:
從結(jié)果中我們可以看出,當(dāng)我們顯示給值的時(shí)候,初始化用的n就是我們顯示給的值,而當(dāng)我們不顯示給值的時(shí)候就是用的是默認(rèn)的(缺省的)。
3、缺省的參數(shù)必須從右向左
在給缺省參數(shù)時(shí),缺省參數(shù)的順序一定是從右向左的,也就是說(shuō),缺省參數(shù)一定實(shí)在參數(shù)列表的右端并且一定是連續(xù)的,例如:
而不能出現(xiàn)下面這樣的情況:
置于為什么要這樣,只能說(shuō)是“規(guī)定”,不要問(wèn)為什么。
4、缺省參數(shù)不能聲明和定義同時(shí)給
缺省參數(shù)還有一點(diǎn)需要注意的是,缺省參數(shù)不能聲明和定義同時(shí)給:
這樣做的目的主要是為了防止聲明和定義給的缺省值不一致,從而導(dǎo)致調(diào)用存在歧義。
但我們可以只在聲明給,定義不給:
三、函數(shù)重載
1、為什么要引入函數(shù)重載?
我們?cè)贑語(yǔ)言中有時(shí)候會(huì)需要一些邏輯非常相似,但就是參數(shù)類型不同的函數(shù),比如我們?cè)倥判蛑薪?jīng)常要使用到的交換兩個(gè)變量的函數(shù)Swap,對(duì)于交換int和double類型,我們就必須寫(xiě)兩個(gè)不同名的函數(shù):
這樣是不是很煩啊?
所以為了解決這個(gè)問(wèn)題,C++就引入了函數(shù)重載。
2、函數(shù)重載的基本用法
有了函數(shù)重載,我們上面的這兩個(gè)函數(shù)就可以同名了:
函數(shù)重載有三個(gè)要點(diǎn):
1.參數(shù)的類型不同
2.參數(shù)的順序不同(不同類型的參數(shù)的順序不同)
3.參數(shù)的個(gè)數(shù)不同
上面的例子就是類型不同。
然后是參數(shù)的順序不同,一定要是不同類型的參數(shù)的順序不同,例如下面這個(gè)例子:
而如果只是參數(shù)名不同,而兩個(gè)參數(shù)都是同一類型就會(huì)報(bào)錯(cuò):
因?yàn)榫幾g器是根據(jù)不同類型參數(shù)的位置來(lái)判斷到底該調(diào)用哪一個(gè)函數(shù)的,這樣做會(huì)讓編譯器存在歧義。
然后是個(gè)數(shù)不同:
這個(gè)祈其實(shí)就不用多說(shuō),編譯器會(huì)根據(jù)參數(shù)的個(gè)數(shù)來(lái)判斷到底該調(diào)用哪一個(gè)函數(shù)。
3、當(dāng)函數(shù)重載跟缺省參數(shù)碰到一起
而如果函數(shù)重載跟缺省參數(shù)碰到一起,會(huì)發(fā)生什么呢?
例如下面這個(gè)例子:
從結(jié)果我們可以看出是沒(méi)問(wèn)題的,因?yàn)樗鼈冎g符合了參數(shù)類型不同,而參數(shù)有沒(méi)有缺省值是沒(méi)有關(guān)系的。
但下面這個(gè)例子就不同了:
在這個(gè)例子中,雖然兩個(gè)函數(shù)也滿足了函數(shù)重載的條件只以——參數(shù)的個(gè)數(shù)不同,但是編譯器在調(diào)用的時(shí)候可能會(huì)存在歧義,因?yàn)橄裆厦孢@樣只給一個(gè)參數(shù)的調(diào)用,對(duì)于兩個(gè)函數(shù)來(lái)說(shuō)都行得通,第一個(gè)函數(shù)本身就只有一個(gè)參數(shù),而第二個(gè)有缺省值的函數(shù)只給一個(gè)參數(shù)也是能正常調(diào)用的。
所以如果在重載函數(shù)的時(shí)候想要給缺省參數(shù),就一定要注意調(diào)用歧義的情況。
四、引用
1、為什么要引入引用?
我們都知道C語(yǔ)言有指針,但C++的祖師爺在使用指針的時(shí)候發(fā)現(xiàn):C語(yǔ)言這個(gè)指針,用起來(lái)也太不方便了吧。例如我們要寫(xiě)一個(gè)交換函數(shù)Swap:
如上面這個(gè)例子,祖師爺覺(jué)得有兩個(gè)地方很麻煩,一是在Swap函數(shù)內(nèi)想要拿到數(shù)據(jù)就必須得對(duì)指針解引用,二是在調(diào)用的時(shí)候要對(duì)變量取地址。
所以祖師爺為了解決這兩個(gè)問(wèn)題,在C++中引入了引用。
2、引用的基本用法
引用如果按底層來(lái)理解,其實(shí)它也使用指針來(lái)實(shí)現(xiàn)的,只不過(guò)它較之指針使用起來(lái)更方便。
引用可以理解為是某一個(gè)變量的別名:
引用的定義形式如下:
int a = 1;
int& b = a;
以前在C++中的取地址操作符“&”,現(xiàn)在到了C++中就有了另一個(gè)功能,將其放在類型后面就表示某個(gè)類型的引用。
之所以稱為“別名”是因?yàn)?,引用基本可以?dāng)做被它引用的對(duì)象來(lái)使用,對(duì)引用進(jìn)行自加自減,對(duì)象本身也會(huì)發(fā)生變化:
在使用引用時(shí)候需要注意的一點(diǎn)是引用必須在定義的時(shí)候初始化,所以也就不存在什么“野引用”的說(shuō)法。
還有一點(diǎn)是引用的只想不能改變,也就是說(shuō)一個(gè)引用只能做一個(gè)變量的別名,而不像指針一樣能改變其指向。
3、引用做輸出型參數(shù)
由于引用的特性,所以我們?nèi)蘸髸?huì)經(jīng)常使用引用來(lái)做輸出型參數(shù),比如我們現(xiàn)在實(shí)現(xiàn)一個(gè)簡(jiǎn)單的自加函數(shù):
4、在引用的過(guò)程中權(quán)限不能放大
怎樣理解這一點(diǎn)呢?先看下面這個(gè)例子:
報(bào)錯(cuò)的原因就是,引用將原本變量的權(quán)限放大了,我們知道const修飾的變量是只能讀不能寫(xiě)的(不能改變),但引用默認(rèn)是能讀能寫(xiě)的,這樣就是權(quán)限放大了。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-635981.html
想要消除報(bào)錯(cuò),就可以對(duì)引用也加上const:
這成為“權(quán)限的平移”。
權(quán)限不僅可以“平移”,也可以“縮小”:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-635981.html
到了這里,關(guān)于【C++筆記】C++啟航之為C語(yǔ)言填坑的語(yǔ)法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!