2016-06-20 77 views
4

考慮下面的代碼片斷:函數重載在C++(常量指針)

void foo(const int i) // First foo 
{ 
    std::cout << "First " << i << endl; 
} 

void foo(int i)  // Second foo 
{ 
    std::cout << "Second " << i << endl; 
} 

int main() 
{ 
    int i = 5; 
    foo(i);  
} 

編譯錯誤: redefinition of 'void foo(int)'

由於const S能夠與非const對象被初始化,上述行爲似乎是合理的。現在考慮這個:

void foo_ptr(const int* p) // First foo_ptr 
{ 
    std::cout << "First " << *p << endl; 
} 

void foo_ptr(int* p)  // Second foo_ptr 
{ 
    std::cout << "Second " << *p << endl; 
} 

int main() 
{ 
    int i = 5; 
    foo_ptr(&i);    // Second foo_ptr gets called; prints 'Second 5' 
} 

,因爲它可能是清楚的,我的問題是 - 如果foo在第一種情況下這兩個定義被認爲是相同的,那麼爲什麼它不是所以foo_ptr在第二種情況下?或換句話說,爲什麼const在第一種情況下被忽略,而在第二種情況下卻沒有被忽略?

+0

可能重複http://stackoverflow.com/questions/3682049/functions-with-const-arguments-and-overloading – ThomasMcLeod

+0

那個傻瓜解釋了爲什麼const int和int簽名被認爲是相同的,但OP理解得很好(按照第一個例子)。它並不包括爲什麼指針示例不具有相同的問題。 – paxdiablo

回答

0

why const is ignored in the first case and not so in the second one?

在第一情況下,const是合格的參數本身,而在第二情況下,const是合格的指針對象,而不是指針本身。 Const指針指向const的指針不是一回事。

在第二種情況下,指向const的指針和指向非const的指針是不同的,並且可用於重載。如果您製作指針本身const,即int* const pint* p,則會得到與第一種情況相同的結果。

0

因爲當你聲明

void foo(const int n) 
{ 
} 

所有的const改性劑的作用是防止nfoo()函數內部進行修改。該foo()函數的參數仍然是intconst修飾符不會修改參數的類型。因此,無論

void foo(int n) 

void foo(const int n) 

是採取int參數功能。它們之間的唯一區別是第二個不能修改它的參數,而第一個可以修改它,就像函數中的任何其他非const變量一樣。

然而,存在

void foo(const int *p) 

void foo(int *p) 

一個之間的差被一個指向const整數,另外一個是指向一個可變的整數。他們是不同的類型。

獎金答案:

兩個

void foo(int *p) 

void foo(int * const p) 

具有相同的參數類型。這兩個函數的參數都是指向int的指針。除第二個參數爲const值外,該功能無法修改。

困惑了嗎?

+0

因此,當參數屬於不同類型時,函數定義會有所不同,而不是函數將它們視爲不同類型。 – ibrahim5253

+0

更多,更少或者更少。當應用於類型的「頂部」部分時,'const' /'volatile'限定符實際上不影響參數類型。 –

3
const int* p 

恆定指針的整數,它是一個指向恆定整數(即,[const int] * p而非const [int * p])。這就是爲什麼你有時會看到這樣的代碼:

const int * const p; 

可能似乎多餘的門外漢,但真的不是 - 在這種情況下p是你不能改變一個指針,它指向一個整數你是不允許改變。

因此,您在第二種情況下具有的兩個功能在接受的參數上被認爲是不同的。這也是爲什麼你要調用第二個函數,因爲i絕對不是const整數。

換句話說,儘管const -ing參數不會根據函數簽名改變它,但這不是您在這裏做的。將參數從「指針到int」更改爲「指向const int的指針」會影響簽名。

等效情況下你的第一個代碼段會提供兩種:

void foo_ptr (int * const p) 
void foo_ptr (int * p) 
1

在重載決議,constvolatile指定的參數是顯著,當他們出現在的參數的最外層,除了型號規格。從C++標準,13.1.3.4§:

Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called. [ Example:

typedef const int cInt; 
int f (int); 
int f (const int); // redeclaration of f(int) 
int f (int) { /* ... */ } // definition of f(int) 
int f (cInt) { /* ... */ } // error: redefinition of f(int) 

—end example ] Only the const and volatile type-specifiers at the outermost level of the parameter type specification are ignored in this fashion; const and volatile type-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations. In particular, for any type T, 「pointer to T,」 「pointer to const T,」 and 「pointer to volatile T」 are considered distinct parameter types, as are 「reference to T,」 「reference to const T,」 and 「reference to volatile T.」