const與非const引數呼叫過載函式
阿新 • • 發佈:2019-02-13
先看一段小程式碼:
#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.