C++之函式過載

jun發表於2022-01-02

函式過載

函式過載構成條件

函式過載是C++允許在同一個作用域中宣告幾個名字相同功能相似的函式,函式過載常被用於處理功能類似、資料型別不同的問題。
高階語言在設計時就有一條原則,語言不能存在二義性,C++為了保證語言不存在二義性對函式過載進行約束:
要構成過載函式必須滿足以下幾個條件之一:

  1. 形參型別不同
  2. 形參個數不同
  3. 形參順序不同

通過程式碼實現一個過載函式,以下程式碼位於三個檔案:
test.cpp

#include"func.h"


int main()
{
	f(1, 1.1);

	return 0;
}

func.h

#include<stdio.h>
#include<stdlib.h>

void f(int a, float b);
void f(float a, int b);

func.cpp

#include"func.h"

void f(int a, float b)
{
	printf("f(int a, float b)\n");
}

void f(float a, int b)
{
	printf("f(float a, int b)\n");
}

以上函式構成過載。上面函式構成過載滿足了函式形參順序不同的規則。執行結果為:
image-20220102142053935

從程式執行結果來看,我們不需要指定函式來執行,程式本身根據所傳實參型別來聯絡實際場景判斷用哪個函式,這種方式極大的方便程式設計師。

無法構成過載的特例

值得注意的是,函式的返回型別不同是無法構成函式過載的如:

void f(int a, float b)
{
	printf("f(1)\n");
}

int f(int a, float b)
{
	printf("f(2)\n");
}

還有無法構成過載的特例:

void f(a = 1)
{
    printf("f(a = 1)\n");
}

void f()
{
    printf("f()\n");
}

上面這種情況若是呼叫時有實參,編譯器可以判斷為有形參的函式執行,若無實參呼叫f();,由於上面函式有預設引數,編譯器無法判斷呼叫的是哪個函式,程式也就無法執行。
!!!注意 main函式無法過載!!!

不建議使用函式過載的場景

函式過載對於程式設計師使用起來確實方便,但在有些場景不建議使用函式過載。函式過載使用時最好應用於功能相似的函式。有些時候給函式起不同的名字有利於程式設計師理解函式的功能。舉個例子以下為幾個負責移動螢幕游標的函式:

void moveHome();
void moveAbs(int, int);
void moveRel(int, int, string direction);

將以上幾個函式名字起為move固然也可以,但是這幾個函式構成過載之後函式名就失去了本來擁有的資訊:

void move();
void move(int, int);
void move(int, int, string direction);

顯然第二個命名方式是不如第一個的。

C語言無法構成過載

在vs2019環境中將上面三個檔案中的.cpp字尾全改為.c字尾,編譯程式後程式報錯

image-20220102162759548

由此可以看出C語言不支援函式過載。
那麼為什麼C語不支援函式過載而C++支援呢?

函式名字修飾

從程式碼到程式經過預處理,編譯,彙編,連結幾個過程,C++為了支援函式過載在編譯階段對函式名做了修飾,即名字修飾。由於Windows系統下名字修飾較為複雜,後面的名字修飾演示全為Linux系統下的演示。
在Linux系統下將test.cpp檔案進行彙編後反彙編檢視:

image-20220102173430008

image-20220102173534172

對比兩個函式修飾過的名字和諮詢大佬後知道Linux系統下函式名修飾規則:

_Z+函式名長度+函式名+形參型別
形參型別:
i int
f float
c char
pi *int
其它照此類推

由此可以看出,被以上的3個條件約束的函式過載時修飾後的名字是不會重複的,如此才能構成函式過載

C語言反彙編

我們可以通過此方法來看一下C語言的名字修飾情況,揭祕以下C語言為什麼不知此過載。
將一個f函式註釋掉後反彙編:

image-20220102192958741

可以看到,f函式是沒有經過任何修飾的。所以每個f函式名字都是一樣的,編譯器無法區分函式,所以無法構成過載。
Windows下反彙編的函式名字不太好看,但還是可以通過一些方法看到。

image-20220102193921311

如上圖,修飾過的函式名有些複雜,不利於分析,關於Windows下的函式名修飾規則可以在搜尋引擎上看一下。

相關文章