天天看點

C++:函數重載(你不知道的細節)

----------------------别讓現實太餓,吃了夢想

文章目錄

    • 前言
    • Ⅰ- 初識
    • Ⅱ- 函數特征标
    • Ⅲ - 調用和原型比對
        • 1.強轉
        • 2.引用
        • 3.const
    • Ⅲ - 名稱修飾

前言

在不同的場景下,我們經常希望使用同一個函數名完成相同的任務,但是使用不同的參數清單。(例如:一個add函數完成兩個int變量的相加,另一個add函數完成兩個double變量的相加)

Ⅰ- 初識

我們通過一個執行個體來完成前言提到的例子:

int add(int a,int b){
	return a+b;
}

double add(double a,double b){
	return a+b;
}

int main(){	
	cout<<add(2,3)<<endl;
	cout<<add(2.2,3.2)<<endl;
	return 0;
}
           

這就是通過函數的重載完成一個簡單的例子。

那這是對一個函數的重載嗎?

兩個函數的傳回類型不同:

int add(int a,int b);
double add(int a,int b);
           

❌❌ 這不是函數重載

函數的重載關鍵我們在前言就提到過了----參數清單

Ⅱ- 函數特征标

函數的重載關鍵是 參數清單---- 函數特征标。

函數特征标不同的要求:

  1. 參數數目
  2. 參數類型
  3. 參數的排列順序

C++允許定義名稱相同的函數,但是前提需要是函數的特征标不同。

Ⅲ - 調用和原型比對

函數調用時對多個定義的重載函數的選擇----重載解析,是我們我們運用函數重載的難點。

1.強轉

下面看一組測試:

聲明:

void fun(int a);     // #1
void fun(float a);   // #2
void fun(char *s);   // #3
           

調用:

fun(6.0);    //to #2
fun(6);      //to #1
fun("messi");//to #3
           

這似乎沒什麼問題,但是我們看這個調用:

long a=6;
fun(a);
           

它将與哪一個比對? 它不與任何一個比對! 因為 有兩個函數都能接受以數字為實參。即使類型不比對,但是有兩種類型轉換的反方式。 在這種情況下,C++會将其視為錯誤。

我們得到:函數重載中,在沒有完全比對的情況下,編譯器隻會接受有且隻有一種可以強轉的函數調用。

2.引用

聲明:

void fun(int a);  // #1
void fun(int &a); // #2
           

調用:

int a=6;
fun(a);
           

這也是錯誤的!

調用似乎和 #1是完全比對的,但是對于編譯器而言,這兩個都比對,在檢查函數的特征标時,将類型引用和類型本身視為同一個特征标。

3.const

聲明:

void fun(const int a);
void fun(int a);
           

調用:

int x=6;
fun(x);
           

.

.

.

兩個函數聲明都能接受調用,那會像引用一樣報錯嗎?

不會報錯!! 使用第二個原型。

對于const類型,編譯器會根據實參是否為const來決定使用哪一個原型。

意思就是,編譯器将== const== 和 非const 視為兩個函數特征标。

Ⅲ - 名稱修飾

在程式内部而言,如何跟蹤多個名字相同的重載函數呢?意思就是 編譯器是如何區分這些重載函數的?

C++編譯器通過-----名稱修飾 來完成。

比如說 :void fun(int a)

這種格式對于我們來言很适合,但是對于對于編譯器來說并不友好,編譯器會轉換為自己的内部表示。

值得注意的是: 不同的編譯器,對同一函數的名稱修飾是不一樣的。

這個可能會造成什麼問題呢?

假設我們将自己的函數裝入庫中,到程式的連結階段,連結器無法将一個編譯器生成的函數調用和另一個編譯器生成的函數定義比對。

c++

繼續閱讀