解析C 中函式過載的實現原理

2021-08-03 09:21:46 字數 1922 閱讀 2476

一、定義

當兩個及兩個以上函式共用乙個函式名,但是形參個數或者型別不同,編譯器根據實參與形參的型別及

個數的最佳匹配,自動確定呼叫那乙個函式,這就是函式的過載。

換而言之,在同一作用域,一組函式名相同,引數列表不同(個數和型別),返回型別可同,可不同的情況下,編譯器根據呼叫者傳入的引數型別和個數可以唯一可以唯一確定呼叫哪個函式,這也就是函式的過載。c++中才有此特性。

例如:

void

overloadfunc

(int

x,int d){}

voido

verloadfunc

(int

x, double d){}

void

overloadfunc

(double

x, int d){}

這個是引數列表型別不同的

例子,個數不同在此不做贅述。

注意以下三點:

1、為什麼返回值型別不同不可以構成過載呢?因為有的函式雖然有返回值型別,但不與引數表示式運算,而作一條單獨的語句。

2、怎樣會引起二義性?因為函式的過載與帶預設值(預設)的函式一起使用時有可能引起二義性:

例如:                     

void circle(int r=0,int x=0,int y=0);

void circle(int r);

當進行呼叫時,編譯系統無法確定呼叫哪乙個函式。

3、在函式呼叫時,如果給出的實參型別和形參型別不相符,c++編譯器會自動做出型別轉換工作。若轉換成功,則會產生不可識別的錯誤。

例如:

void fa(int x);

void fa(long x);

雖然這兩個函式滿足過載條件,但如果用下面**去呼叫,就會出現上述錯誤。

int c=fa(5.56);

這是因為編譯器無法確定將5.56轉化成int還是long型別。

二、過載的底層原理

其實c++函式過載底層實現原理是c++利用name mangling(傾軋)技術,來改名函式名,區分引數不同的同名函式。

c++中,這三個函式如果在主函式中被呼叫選擇哪乙個,由編譯器自身決定。那麼不同編譯器底下函式的命名風格又是怎樣的呢?請接著往下看

再例如:

#includeusing namespace std;

int add(int a, int b)

double add(double a, double b)

int main()

這段**兩個函式add引數的型別不同,在windows環境下和linux環境下編譯器編譯完成後的函式名的命名風格也就不同。以下是在vs2013編譯器下編譯完成map檔案中的函式名,可以看出addd命名發生改變,一般是 ?[函式名]@@yahhh@z (只用函式名和ya後面的格式和@z是固定的,剩下的都是固不定的,它的命名代了返回值的引數型別。(h—int,n—double,x—void) 。

同樣在linux環境下,這段**中函式的命名也發生改變,一般是_z[函式名長度][函式名][引數列表的型別首字母]。

總的來說:原始檔通過編譯後,將相同函式名,按照一定的格式,改變成可以區分的,去除了函式在呼叫時的二義性,從而實現函式的過載。 

解析c 中函式過載的實現原理

1.剖析c 是如何實現過載的?2.解析面試題 在c 程式中呼叫被 c 編譯器編譯後的函式,為什麼要加 extern c 宣告?1.函式過載的實現原理 函式過載的定義 當兩個及兩個以上函式共用乙個函式名,但是形參個數或者型別不同,編譯器根據實參與形參的型別及 個數的最佳匹配,自動確定呼叫那乙個函式。也...

C 函式過載的實現原理

對於c 來說,多個函式可以同名,但是這些函式的引數型別必須不一樣,也就是說c 中相同的函式名函式引數不同代表了不同的函式,當你去呼叫這些函式時,編譯器可以根據你的傳入引數的型別去判斷你呼叫的是哪個函式。但是c 編譯器是怎麼實現的呢?先看看c對於函式的處理 執行命令 gcc s main c.c o ...

c 函式過載的實現原理

1.c 問什麼引入函式過載 在c語言中,如果我們寫兩個函式名相同的函式,編譯器會告訴我們,函式重定義的錯誤。我們還會遇到下面這個問題 如果我們寫乙個計算int型別的加法,另乙個計算double型別的加法,我們必須起兩個不同的函式名。而在c 中我們可以解決這兩個問題。我們可以用相同的函式名,只有引數列...