通俗易懂講編程——編譯器是如何識別同名函數的


通俗易懂講編程——編譯器是如何識別同名函數的


前一陣,一位朋友問我,編譯器是如何知道當傳入不同參數就會調用同一個類中的同名函數,我想,這也許是很多初學者經常遇到的問題,今天小豆君就來說說這個原理。

在講原理之前,我先來講一個生活中的例子——取名字。

好聽好記的漢字就那麼多,很多家長在給孩子起名字時難免“撞衫”。比如,我高中一班的一個同學叫“劉洋”,二班的同學也有個叫“劉洋”,那麼我們為了區分這兩個人,就可能會給她們重命名為“一班劉洋”,“二班劉洋”,這樣就可以準確區分啦。

而在編程中,好用簡單的英文也就是那麼多個,況且我英文水平也不高,一堆程序員在一起編程,難免會起重名字。

講到這裡,我想聰明的小夥伴們就發現了,其實,在我們程序中編譯器就是將所有的類名,函數名,參數類型,名字空間等等拼接起來,從而為每個函數生成了一個唯一的名字。

例如:

<code>class MyClass
{
public:
int fun();
int fun(int param1);
int fun(const int& param1);
int fun(double param1);
int fun(double param1, const string& param2);
int fun() const;
};
/<code>

上面的這段代碼定義了5個同名參數,那麼這些函數接口在編譯器中的名字可能分別為

<code>class MyClass
{
public:
//註釋為對應編譯器重新生成的名字
int fun();//=>MyClass_fun
int fun(int param1);//=>MyClass_fun_int
int fun(const int& param1);//=>MyClass_fun_const_int
int fun(double param1);//=>MyClass_fun_double
int fun(double param1, const string& param2);//=>MyClass_fun_double_string
int fun() const;//=>MyClass_fun_const
};
/<code>

當我在程序中寫

<code>MyClass c;
c.fun(25);
/<code>

那麼,編譯器就會分析實例c是MyClass類型,只有一個參數,且25為整數類型,所以c.fun(25)被編譯之後,其函數名可能變為MyClass_fun_int,那麼編譯器就可以根據這個唯一的名字找到我這個接口的入口地址,從而執行該入口地址所對應的代碼段。

所以,你就不難理解下面的重載條件:

  • 參數個數不同,可以重載
  • 參數個數相同,但參數類型不同也可重載
  • const參數可以重載,可以把const修飾的對象和普通對象看作是兩種類型

我們還知道,返回值是不能作為重載條件的,請看下面代碼

比如我在MyClass類中又定義了一個返回string類型的fun接口

<code>string fun();
/<code>

那麼請看下面的代碼,編譯器該如何翻譯

<code>MyClass c;//假設返回值可以作為重載條件
int val1 = c.fun();//重命名為 int_MyClass_fun
string val2 = c.fun();//重命名為string_MyClass_fun
c.fun();//這個該如何重命名呢?int_MyClass_fun還是string_MyClass_fun?
/<code>

從上面的示例中,我們可以看出,正因為C++可以忽略接口的返回值,所以如果只用返回值來作為重載條件是不夠的,也是不可取的。所以編譯器會在這裡報重定義的錯誤。


分享到:


相關文章: