日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++基础03-C++对c的拓展-函数

發(fā)布時間:2025/3/15 c/c++ 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++基础03-C++对c的拓展-函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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

c 語言中有宏函數(shù)的概念。宏函數(shù)的特點是內(nèi)嵌到調(diào)用代碼中去,避免了函數(shù)調(diào)用 的開銷。但是由于宏函數(shù)的處理發(fā)生在預處理階段,缺失了語法檢測 和有可能帶來的語 意差錯

特點:

???? 1)內(nèi)聯(lián)函數(shù)聲明時inline關(guān)鍵字必須和函數(shù)定義結(jié)合在一起,否則編譯器會直接忽略內(nèi)聯(lián)請求。

???? 2)C++編譯器直接將函數(shù)體插入在函數(shù)調(diào)用的地方 。

???? 3)內(nèi)聯(lián)函數(shù)沒有普通函數(shù)調(diào)用時的額外開銷(壓棧,跳轉(zhuǎn),返回)。

???? 4)內(nèi)聯(lián)函數(shù)是一種特殊的函數(shù),具有普通函數(shù)的特征(參數(shù)檢查,返回類型等)。

???? 5) 內(nèi)聯(lián)函數(shù)由 編譯器處理,直接將編譯后的函數(shù)體插入調(diào)用的地方,宏代碼片段 由預處理器處理, 進行簡單的文本替換,沒有任何編譯過程。

???? 6)C++中內(nèi)聯(lián)編譯的限制:

??????????? 不能存在任何形式的循環(huán)語句

??????????? 不能存在過多的條件判斷語句

??????????? 函數(shù)體不能過于龐大

??????????? 不能對函數(shù)進行取址操作

??????????? 函數(shù)內(nèi)聯(lián)聲明必須在調(diào)用語句之前

??? 7)編譯器對于內(nèi)聯(lián)函數(shù)的限制并不是絕對的,內(nèi)聯(lián)函數(shù)相對于普通函數(shù)的優(yōu)勢只是省去了函數(shù)調(diào)用時壓棧,跳轉(zhuǎn)和返回的開銷。因此,當函數(shù)體的執(zhí)行開 銷遠大于壓棧,跳轉(zhuǎn)和返回所用的開銷時,那么內(nèi)聯(lián)將無意義

內(nèi)聯(lián)函數(shù)總結(jié):

??????? 優(yōu)點:避免調(diào)用時的額外開銷(入棧與出棧操作)

??????? 代價:由于內(nèi)聯(lián)函數(shù)的函數(shù)體在代碼段中會出現(xiàn)多個“副本”,因此會增加代碼段的空間。

??????? 本質(zhì):以犧牲代碼段空間為代價,提高程序的運行時間的效率。

??????? 適用場景:函數(shù)體很“小”,且被“頻繁”調(diào)用。

#if 0 #include<iostream> using namespace std;//代碼比較少時才采用inline函數(shù) //若代碼比較多,有復雜業(yè)務時即使申明為inline函數(shù),也不會采用inline函數(shù)的執(zhí)行方式 void PrintAB1(int a, int b) {cout << "a=" << a << endl;cout << "b=" << b << endl; } void test01() {int a = 10;int b = 10;for (int i = 0; i < 1000; i++){a++;b++;PrintAB1(a, b); //函數(shù)壓棧 a,b壓棧,形參拷貝實參,執(zhí)行語句,返回值再出棧 有一定的空間開銷} }//宏函數(shù) 解決了函數(shù)壓棧 出棧 但解決不了參數(shù)的替換問題(簡單的參數(shù)拷貝) #define MAX(a,b) \(a)>(b)?(a):(b)int max(int a, int b) {return (a > b) ? a : b; }void test02() {int a = 20;int b = 10;int c = 0;c = MAX(a, b);cout << c << endl; //20c = MAX(a++, b++); //(a++)>(b++)?(a++):(b++) 宏函數(shù)沒有語法檢測能力,預處理時執(zhí)行cout << c << endl; //21c = max(a++, b++);cout << c << endl; //22 }inline void PrintAB2(int a, int b) {cout << "a=" << a << endl;cout << "b=" << b << endl; }void test03() {int a = 10;int b = 10;for (int i = 0; i < 1000; i++){a++;b++;PrintAB2(a, b); //相當于將函數(shù)展開} } inline void PrintAB3(int a, int b); //在申明是使用inline,但是函數(shù)體沒有加inline 還是普通函數(shù)void PrintAB3(int a, int b){cout << "a=" << a << endl;cout << "b=" << b << endl; }int main() {test02(); } #endif

二、函數(shù)的默認參數(shù)和占位參數(shù)

1、默認參數(shù)

通常情況下,函數(shù)在調(diào)用時,形參從實參那里取得值。對于多次調(diào)用用一函數(shù)同一 實參時,C++給出了更簡單的處理辦法。給形參以默認值,這樣就不用從 實參那里取值了。

在默認參數(shù)規(guī)則 ,如果默認參數(shù)出現(xiàn),那么右邊的都必須有默認參數(shù)? 存在默認參數(shù)時, 當置于右側(cè)。

默認參數(shù)規(guī)則:

???????? 只有參數(shù)列表后面部分的參數(shù)才可以提供默認參數(shù)值

??????? 一旦在一個函數(shù)調(diào)用中開始使用默認參數(shù)值,那么這個參數(shù)后的所有參 數(shù)都必須使用默認參數(shù)值

2、占位參數(shù)

??????? 函數(shù)占位參數(shù)

?????? 占位參數(shù)只有參數(shù)類型聲明,?沒有參數(shù)名聲明

?????? ?般情況下,在函數(shù)體內(nèi)部?法使?占位參數(shù)

#include<iostream> using namespace std;//1、默認參數(shù) void func1(int a) {cout << "a=" << a << endl; }void func2(int a = 666) {cout << "a=" << a<<endl; } void test01() {int a = 200;func1(a); //200//func1(); //編譯錯誤func2(a); //200func2(); //正確 666 } int get_volume1(int len, int width, int height) {cout << "len=" << len << endl;cout << "width=" << width << endl;cout << "height=" << height << endl;return len*width*height; } int get_volume2(int len, int width, int height=1) { //左邊有默認值時,右邊必須有默認值cout << "len=" << len << endl;cout << "width=" << width << endl;cout << "height=" << height << endl;return len*width*height; } void test02() {int len = 10;int w = 20;int h = 30;cout << "體積是:"<<get_volume1(len, w, h) << endl; //6000cout << "體積是:" << get_volume2(len, w) << endl; //200 從左向右對應參數(shù) }//2、占位參數(shù) void funn1(int x) {cout << "x=" << x << endl; } void funn2(int x, int); void funn2(int x,int) { //第二個參數(shù)無意義,但必須傳遞值 cout << "x=" << x << endl; } void funn3(int x, int = 0) { //第二個參數(shù)無意義,但必須傳遞值 cout << "x=" << x << endl; } void test03() {int a = 10;funn1(a);funn2(10, 20);//funn2(10); //錯誤funn3(10, 20);funn3(10); //正確 } int main() {//test01();test02(); }

三、函數(shù)重載

1、函數(shù)重載(Function Overload):用同一個函數(shù)名定義不同的函數(shù),當函數(shù)名和不同的參數(shù)搭配時函數(shù)的含義不同

2、重載規(guī)則(參數(shù)個數(shù)不同 參數(shù)類型不同 參數(shù)順序不同):(前提是在同一作用域之內(nèi))

?????? ? 1,函數(shù)名相同。

???????? 2,參數(shù)個數(shù)不同,參數(shù)的類型不同,參數(shù)順序不同,均可構(gòu)成重載。

???????? 3,返回值類型不同則不可以構(gòu)成重載。 僅返回值類型不同,不是重載。

3、調(diào)用規(guī)則

??????? 1,嚴格匹配,找到則調(diào)用。

??????? 2,通過隱式轉(zhuǎn)換尋求一個匹配,找到則調(diào)用。

4、編譯器調(diào)用重載函數(shù)的準則:

??????? 1.將所有同名函數(shù)作為候選者

??????? 2.嘗試尋找可行的候選函數(shù)

??????? 3.精確匹配實參

??????? 4.通過默認參數(shù)能夠匹配實參

??????? 5.通過默認類型轉(zhuǎn)換匹配實參

??????? 6.匹配失敗

??????? 7.最終尋找到的可行候選函數(shù)不唯一,則出現(xiàn)二義性,編譯失敗。

??????? 8.無法匹配所有候選者,函數(shù)未定義,編譯失敗。

5、重載底層實現(xiàn)(name mangling)

?????? C++利用 name mangling(傾軋)技術(shù),來改名函數(shù)名,區(qū)分參數(shù)不同的同名函數(shù)。 實現(xiàn)原理:用 v c i f l d 表示 void char int float long double 及其引 用。

?????? void func(char a); // func_c(char a)

?????? void func(char a, int b, double c); //func_cid(char a, int b, double c)

6、函數(shù)重載與函數(shù)默認參數(shù)

?????? 一個函數(shù),不能既作重載,又作默認參數(shù)的函數(shù)。當你少寫一個參數(shù)時,系統(tǒng)無法確認是重載還是默認參數(shù)。

#if 1 #include<iostream> using namespace std;//函數(shù)的返回值 函數(shù)的形參列表(參數(shù)個數(shù),參數(shù)類型,參數(shù)順序) /* int func(int a, int b) {//... } */ //c語言中只要函數(shù)名相同 無法通過編譯 //1、c++中增加了函數(shù)重載:函數(shù)名相同,形參列表不同 //若函數(shù)名相同,形參列表相同,函數(shù)返回值不同,則不可以通過編譯 //2、函數(shù)返回值并不是構(gòu)成函數(shù)重載的條件 //3、如果有函數(shù)重載,不要寫默認參數(shù),為了避免調(diào)用出現(xiàn)函數(shù)沖突//調(diào)用規(guī)則 // <1>如果能夠嚴格匹配調(diào)用完全匹配 // <2>如果沒有完全匹配,調(diào)用隱式轉(zhuǎn)換 // <3>如果都匹配不到,調(diào)用失敗 int func1(int a, int b) {cout << "func1(int a, int b) " << endl;return 0; } int func1(int a, char b) {cout << "func1(int a, char b)" << endl;return 0; } /* void func1(int a, char b) {cout << "func2" << endl; } */ void test01() {func1(1, 2); //func1(int a, int b)func1(1, 'a'); //func1(int a, char b) }int func2(int a, char b) {cout << "func2(int a, char b)" << endl;return 0; } int func2(int a, char b, int c = 0) { //等價于int func2(int a, char b, int=0) {cout << "func2(int a, char b, int c = 0)" << endl;return 0; } //如果有函數(shù)重載,不要寫默認參數(shù),為了避免調(diào)用出現(xiàn)函數(shù)沖突 void test02() {//func2(1, 'a'); 編譯錯誤 編譯器不會選擇func2(1, 'a', 22); }int func3(int a, char b) {cout << "func3(int a, char b)" << endl;return 0; } int func3(int a, char b, int c) { //等價于int func3(int a, char b, int) {cout << "func3(int a, char b, int c)" << endl;return 0; }void test03() {func3(1, 'a'); func3(1, 'a', 22); }void print1(int a) {cout << "print1(int a)" << " a=" << a << endl; } void print1(double a) {cout << "print1(double a)" <<" a=" << a << endl; } /* void print1(char a) {cout << "print1(char a)" << " a=" << a << endl; }*/ void test04() {print1(10); //print1(int a) a = 10print1(1.2); //print1(double a) a = 1.2print1('A'); //print1(int a) a = 65print1(3.1f); //print1(double a) a=3.1 隱式轉(zhuǎn)換//print1("ter"); 報錯沒有匹配 } int main() {//test01();//test02();//test03();test04();return 0; } #endif

7、函數(shù)重載和函數(shù)指針結(jié)合

???????????? 函數(shù)重載與函數(shù)指針

???????????? 當使?重載函數(shù)名對函數(shù)指針進?賦值時

???????????? 根據(jù)重載規(guī)則挑選與函數(shù)指針參數(shù)列表?致的候選者

???????????? 嚴格匹配候選者的函數(shù)類型與函數(shù)指針的函數(shù)類型

8、函數(shù)指針基本語法

?????? //?法?:

????? //聲明?個函數(shù)類型

????? typedef void (myTypeFunc)(int a,int b);

????? //定義?個函數(shù)指針

????? myTypeFunc *myfuncp = NULL; //定義?個函數(shù)指針 這個指針指向函數(shù)的??地址

????? //?法?:

????? //聲明?個函數(shù)指針類型

????? typedef void (*myPTypeFunc)(int a,int b) ; //聲明了?個指針的數(shù)據(jù)類型

???? //定義?個函數(shù)指針

????? myPTypeFunc fp = NULL; //通過 函數(shù)指針類型 定義了 ?個函數(shù)指針 ,

????? //?法三:

????? //定義?個函數(shù)指針 變量

????? void (*myVarPFunc)(int a, int b);

#include<iostream> using namespace std;int func(int a, int b) {cout << "func" << endl;return 0; }//1、定義一種函數(shù)類型 typedef int(MY_FUNC)(int, int); //第一個int為返回值類型 //(int, int)為參數(shù)列表 //MY_FUNC為函數(shù)類型名 void test01() {//1.MY_FUNC *fp = NULL;fp = func;fp(10, 20); //func(*fp)(10, 20); //func }//2、定義一個指向函數(shù)類型的指針類型 typedef int(*MY_FUNC_P)(int, int); //MY_FUNC_P為指向int func(int a, int b) 函數(shù)類型的指針類型名 void test02() {MY_FUNC_P fp = NULL;fp = func;fp(10, 20); //func }//3、通過函數(shù)類型直接定義 常用 void test03() {int(*fp3)(int, int) = NULL;fp3 = func;fp3(100, 200); //func } int funcc(int a, int b) {cout << "funcc(int a, int b)" << endl;return 0; } int funcc(int a, int b,int c) {cout << "funcc(int a, int b,int c)" << endl;return 0; } void test04() {int(*fp3)(int, int) = NULL;fp3 = funcc; //fp3-->funcc(int a, int b)fp3(100, 200); //funcc(int a, int b)//fp3(10, 20, 30); 編譯錯誤 函數(shù)重載和函數(shù)指針重載是兩回事 }//實際上在給函數(shù)指針賦值的時候 是會發(fā)生函數(shù)重載匹配的 //在調(diào)用函數(shù)指針時,所調(diào)用的函數(shù)就已經(jīng)是固定的了 int main() {//test01();//test02();//test03();test04();return 0; }

函數(shù)重載總結(jié):

??????? 重載函數(shù)在本質(zhì)上是相互獨立的不同函數(shù)

?????? 函數(shù)的函數(shù)類型是不同的

?????? 函數(shù)返回值不能作為函數(shù)重載的依據(jù)

?????? 函數(shù)重載是由函數(shù)名和參數(shù)列表決定的。

總結(jié)

以上是生活随笔為你收集整理的C++基础03-C++对c的拓展-函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。