c++學習筆記(二、c++對c函數的擴展)

學習語言都是比較枯燥的,不過不學會語言知識,直接看代碼確實不好。今天繼續c++第二天

2.1 內聯函數

c++的內聯函數和c的一樣,本來不想寫的,不過當做一次複習吧。
特點:

  1. 內聯函數聲明時inline關鍵字必須和函數定義結合在一起
  2. 編譯器直接將函數體插入到函數調用的地方
  3. 內聯函數沒有其他函數調用時的開銷(壓棧、跳轉、返回)
  4. 內聯函數是一種特殊的函數,具有普通函數的特徵。(可以檢查參數,返回值等)
  5. 內聯函數由編譯器,直接將編譯後的函數體插入調用的地方,宏代碼片段 由預處理器處理,進行簡單的文本替換,沒有任何編譯過程。
  6. C++中內聯編譯的限制
    不能存在任何形式的循環語句。
    不能存在過多的條件判斷語句。
    函數體不能過於龐大。
    不能對函數進行取址操作
    函數內聯聲明必須在調用語句之前
  7. 當函數體的執行開銷遠大於壓棧,跳轉和返回所用的開銷時,那麼內聯將無意義。
    來自《黑馬程序員C++課程》

2.2 函數默認參數和佔位參數

c++中函數是支持默認參數的

int get_area(int len, int width, int height)
{
    return len * width * height;
}

int get_area2(int len = 10, int width = 20, int height = 30)
{
    return len * width * height;
}

int main(int argc, char **argv)
{
    cout << "hello c++ " << my_spaceA::my_spaceB::haha << endl;
    int area = 0;

    area = get_area(10, 20, 30);
    printf("area = %d\n", area);

    area = get_area2();
    printf("area = %d\n", area);
	area = get_area2(20, 30, 40);
    printf("area = %d\n", area);
    return 0;
}

函數的默認參數就是在函數的形參加個等號=什麼,如果函數有默認值的時候,傳參的時候可以不傳參數的,如果我們傳入了參數的話,函數就會用我們傳入的參數,而不用默認值。

如果某個參數是默認參數,那麼它後面的參數都要是默認參數,默認參數是從右到左的,因爲填參數的時候是從左到右的,這樣纔不衝突。

這樣是正確的:
int get_area2(int len, int width = 20, int height = 30);
int get_area2(int len, int width , int height = 30);

這樣就是錯誤的:
int get_area2(int len = 24, int width , int height);

佔位參數:
佔位參數只有參數類型的聲明,沒有參數名的聲明
一般情況下,函數是無法使用佔位參數的

int get_area(int len, int width, int height, int)
{
    return len * width * height;
}
//最後一個參數int  就是佔位參數

給函數傳參的時候,也需要傳4個參數:
get_area(10, 20, 30, 40)
感覺有點難受,傳入40也沒啥用,體驗一下默認參數+佔位參數

int get_area(int len, int width, int height, int = 0)
{
    return len * width * height;
}

這樣傳參就是3個參數和4個參數都可以的,具體用法,有待以後學習。

2.3 函數重載

C++ 不允許變量重名,但是允許多個函數取相同的名字,只要參數表不同即可,這叫作函數的重載(讀“蟲載”,不讀“衆載”,其英文是 overload)。重載就是裝載多種東西的意思,即同一個事物能完成不同功能。

2.3.1 重載的規則

  1. 函數名相同
  2. 參數個數不同,參數的類型不同,參數順序不同,均可構成重載
  3. 返回值類型不同不可以構成重載
    例子:
    在這裏插入圖片描述

2.3.2 調用準則

1.嚴格匹配,找到則調用
2.通過隱式轉換尋求一個匹配,找到則調用。
3.函數重載的時候,不要用默認參數,使用不當會引起衝突

int get_area(int len, int width, int height)
{
    return len * width * height;
}

還是上面的函數,我調用的時候:

area = get_area(10, 20, 30);
printf("area = %d\n", area);

 area = get_area('a', 20, 30);
 printf("area = %d\n", area);

這兩個都可以匹配的上

2.3.3 重載底層實現

c++利用了name mangling(傾軋)技術,來改變函數名,區分參數不同的同名函數。
實現原理用vcifld表示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)

我們用的時候可以寫函數名一樣的重載,但是底層還是自己轉換成不同名字的,我覺得c語言也可以利用這種命名方式。

2.4 函數重載和函數指針

既然函數可以重載,函數指針在賦值的時候會不會有問題?
顯然是不會的,實際上在給函數指針賦值的時候,是會發生函數重載匹配的,如果能匹配上指針,這個指針的地址就固定了,不能在重載其他函數了。所以在調用的時候,調用的函數也固定了。

int get_area(int len, int width, int height)
{
    printf("int int int\n");
    return len * width * height;
}

int get_area(int len, int width, int height, int aa)
{
    printf("char int int\n");
    return (*len) * width * height;
}

main函數:

int main(int argc, char **argv)
    {
        cout << "hello c++ " << my_spaceA::my_spaceB::haha << endl;
        int area = 0;

        int (*areap)(int, int, int) = get_area;
        areap(10, 20, 30);    //這個是ok的
        areap(10, 20, 30, 40);   //這個是編譯不過的
        return 0;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章