最近需要用C++做一些跨平臺的組件普舆,我自己本身對C++的語法不是特別熟練,也算是邊寫邊學(xué)表悬。
記錄了一些平時開發(fā)過程中用到的語法筆記弥锄。
1.C++支持函數(shù)重載,C不支持。底層用了namemangling技術(shù)籽暇,通過編譯器把函數(shù)名字改掉窘行,每個方法名不一樣。不同編譯器有不同的生成規(guī)則图仓。
2.extern "C":
-
被extern "C" 修飾的代碼會按照C語言的方式去編譯。
extern "C" { void fun(){ count << "func()" << endl; } }
如果函數(shù)同時有聲明和實現(xiàn)但绕,要讓函數(shù)聲明被extern "C" 修飾救崔,函數(shù)的實現(xiàn)可以不修飾。
假如有兩個函數(shù)是通過.c(C語言)的方式進(jìn)行實現(xiàn)的捏顺,那么在cpp的文件中六孵,假如想使用這兩個函數(shù)的話,不僅要聲明幅骄,并且需要的在聲明外要用 extern "C" 修飾劫窒。告訴編譯器,這兩個方法是用C語言來實現(xiàn)的拆座。
-
當(dāng)然也可以這么寫
extern "C" { #include "math.h"http://include的作用:把math.h的內(nèi)容原封不動的拷貝一份主巍。 }
-
那么一個函數(shù)聲明既要給C調(diào)用又要給C++調(diào)用怎么辦呢?用
__cplusplus
宏來判斷你是否在C++的環(huán)境#ifdef __cplusplus extern "C" { #endif //這里是是你的聲明或者代碼,xxx #ifdef __cplusplus } #endif
3.防止重復(fù)include:
-
基于include只是執(zhí)行了copy操作挪凑,所以include多次在語法上都沒啥問題孕索,但是代碼量會增多,因此為了防止多次include
可以用以下代碼:首次未定義才進(jìn)入聲明邏輯躏碳。
#ifndef ABC
#define ABC
xxx
- 或者可以用編譯器的特性
#pragma once
來指名頭文件只包含一次搞旭。
兩者區(qū)別:第一種不受編譯器的任何限制,是標(biāo)準(zhǔn)語法菇绵。第二種老編譯器不支持肄渗,兼容性不夠,只針對整個文件咬最。
4.inline內(nèi)聯(lián)函數(shù):本質(zhì)把方法替換成具體實現(xiàn)翎嫡,可以減少函數(shù)調(diào)用的開銷,會增大代碼體積會永乌。但inline只是僅僅是建議編譯器進(jìn)行替換钝的,有時候聲明了也不一定起作用,比如:遞歸铆遭。遞歸是無法內(nèi)聯(lián)的硝桩。
內(nèi)斂函數(shù)和宏都可以減少函數(shù)的開銷,對比宏枚荣,內(nèi)斂函數(shù)有函數(shù)的特性碗脊,有代碼提示。
5.const:被修飾的變量不可修改
如果修飾的是類或者結(jié)構(gòu)體,那么其中的成員也不可更改衙伶。
const修飾右邊的東西
int age = 10;
int height = 20;
int *p = &age; //int * 是一個int指針 p是具體的值
*p = 20; //修改p指向的具體值
p = &height; //修改p的值
const int *p1 = &age;// p1是常量祈坠,*p1是常量,所以不能改年齡
int const *p2 = &age;// 和p1沒區(qū)別
int * const p3 = &age;//p3是常量矢劲,*p3不是赦拘,因此可以年齡。
const int * const p4 = &age;//兩個都不能改
int const * const p5 = &age;//兩個都不能改
6.引用
在C++ 中芬沉,引用可以起到跟指針類似的功能躺同,但指針可以修改,引用必須初始化丸逸,一旦指向了某個變量蹋艺,就不可以再改變。
int age = 10
int &refAge = age;
age = 20;
價值:比指針更安全黄刚。因為指針在中途可以修改指向捎谨,引用不能。
本質(zhì):引用是弱化了的指針憔维。本質(zhì)是指針
7.this
通常一個對象的成員變量是在對象當(dāng)中的涛救,而函數(shù)是放在代碼段的,為了在函數(shù)體內(nèi)用this能訪問到對象本身业扒,這里有個一個隱式參數(shù)州叠,把對象地址傳入函數(shù)體中,然后將對象地址給this進(jìn)行賦值
8.堆的申請和釋放
new和delete或者new[]和delete[]必須成對出現(xiàn)
char *p = new char[4]; //申請連續(xù)的4個字節(jié)凶赁、*p指向第一個咧栗。char類型的數(shù)組
*p = "11";//給第一個字節(jié)賦值
*(p + 1) = "12"http://給第二個字節(jié)賦值
delete[] p;
memset(p,1,4);//p的4個字節(jié)每一個字節(jié)都是1
9.析構(gòu)函數(shù)
對象銷毀時,進(jìn)行調(diào)用虱肄,通過malloc分配的對象free時不會調(diào)用析構(gòu)函數(shù)致板,聲明為pulic才能被外界正常使用。
構(gòu)造方法的順序和析構(gòu)的順序相反咏窿。
構(gòu)造函數(shù): 父類構(gòu)造->子類構(gòu)造
析構(gòu)函數(shù): 子類析構(gòu)->父類析構(gòu)
10.多態(tài)
定義:同一操作作用于不同的對象斟或,可以有不同的解釋,產(chǎn)生不同的執(zhí)行結(jié)果集嵌。
方法的調(diào)用萝挤,默認(rèn)看指針類型進(jìn)行操作,不看實際的對象類型是什么根欧。
很多語言默認(rèn)支持多態(tài)怜珍,C++要實現(xiàn)多態(tài),需要用到虛函數(shù)凤粗。
11.虛函數(shù)
定義:被virtual修飾的成員函數(shù)
只要在父類中聲明為虛函數(shù)酥泛,子類中重寫的函數(shù)也自動變成虛函數(shù)(子類可以省略virtual關(guān)鍵字)
1.有虛函數(shù)存在一個類頂部會多4個字節(jié),這個4個字節(jié)存放的是虛表(虛函數(shù)表)的地址,虛表里面有每個虛函數(shù)的方法地址柔袁。
2.所有對象共用一張?zhí)摫泶舳恪#ㄈ绻嵌嗬^承就多張?zhí)摫恚?/p>
3.因此如果父類指針指向子類對象,析構(gòu)函數(shù)也應(yīng)該定義為虛函數(shù)捶索。否則釋放時無法調(diào)用子類的虛函數(shù)插掂。
12.模版
模版的本質(zhì)類似范型,編譯器會為多類型的入?yún)⑸啥鄠€類型的函數(shù)腥例。
13.類型轉(zhuǎn)換
static_cast:普通轉(zhuǎn)換辅甥,不支持交叉轉(zhuǎn)換。
dynamic_cast:支持交叉轉(zhuǎn)換院崇,會做安全計算。
reinterpret_cast:簡簡單單的二進(jìn)制復(fù)制袍祖。
const_cast:把const轉(zhuǎn)換成非const底瓣。
14.nullptr可以解決NULL的二義性(既代表0又代表空指針)
15.智能指針
傳統(tǒng)指針存在的問題:
1.需要手動管理內(nèi)存。
2.容易發(fā)生內(nèi)存泄漏蕉陋。
3.釋放之后產(chǎn)生野指針捐凭。
智能指針可以解決這些問題。
實現(xiàn)原理類似于裝箱和拆箱凳鬓,用一個內(nèi)部私有指針保存對象茁肠。在釋放時,自動釋放私有的內(nèi)部指針缩举。