1. 程式人生 > >const與非const引數呼叫過載函式

const與非const引數呼叫過載函式

先看一段小程式碼:

#include <iostream>
using namespace std;

void f(const int* ptr){cout<<"Calling const."<<endl;}
void f(int* ptr){cout<<"Calling non-const."<<endl;}

int main ()
{
    int val=1;
    const int* ptr=&val;
    f(ptr);
    return 0;
}

輸出會是什麼呢?這似乎比較顯然:

Calling const
.

類似的,對於下面的程式碼:

#include <iostream>
using namespace std;

void f(const int* ptr){cout<<"Calling const."<<endl;}
void f(int* ptr){cout<<"Calling non-const."<<endl;}

int main ()
{
    int val=1;
    int* ptr=&val;
    f(ptr);
    return 0;
}

我們也有這樣的結果:

Calling non-const
.

但如果以此類推到非指標型別上,也即是按值傳遞的函式時,又會怎麼樣呢

#include <iostream>
using namespace std;

void f(const int val){cout<<"Calling const."<<endl;}
void f(int val){cout<<"Calling non-const."<<endl;}

int main ()
{
    int val=1;
    f(val);
    return 0;
}

事實上,這段程式碼會報出編譯錯誤

[Error] redefinition of ‘void f(int)’

對於const 的情況,其實也是一樣的結果:

#include <iostream>
using namespace std;

void f(const int val){cout<<"Calling const."<<endl;}
void f(int val){cout<<"Calling non-const."<<endl;}

int main ()
{
    const int val=1;
    f(val);
    return 0;
}

輸出同樣為:

[Error] redefinition of ‘void f(int)’

分析

為什麼傳指標與傳值出現了這樣的差異呢?

在傳指標的條件下,函式的原型實際上表明瞭函式能否修改指標所指向的值.所以當傳入一個非const 指標時,就暗含了使用者要改變指標所指向的值的意圖.這時如果呼叫了const 函式,使用者實際上就無法改變指標所指向的值,這就與使用者的初衷相悖.反之,假如使用者傳入了const 指標,就更加不可能為之去呼叫非const 的函數了,因為const 指標所指向的值是受到了保護的,將它轉化為非const 指標是非法的.因此C++做出這樣的安排是完全合理的.

再來看在傳值的情況下,無論使用者傳的是const 引數還是非const 引數,都不會影響引數原本的值.因此,編譯器根本無法區分使用者有什麼樣的意圖,在它的視角里,傳const 與非const 實質上是完全一樣的,因此在這裡const 僅僅起一個修飾作用,這兩個函式的簽名實際上是完全一致的.

同理,對於引用也有類似的結果.

    #include <iostream>
using namespace std;

void f(const int& ref){cout<<"Calling const."<<endl;}
void f(int& ref){cout<<"Calling non-const."<<endl;}

int main ()
{
    int val=1;
    const int& ref=val;
    f(ref);
    return 0;
}

輸出:

Calling const.
#include <iostream>
using namespace std;

void f(const int& ref){cout<<"Calling const."<<endl;}
void f(int& ref){cout<<"Calling non-const."<<endl;}

int main ()
{
    int val=1;
    int& ref=val;
    f(ref);
    return 0;
}

輸出:

Calling non-const.