簡體   English   中英

C ++中的函數重載(const指針)

[英]Function Overloading in C++ (const pointers)

請考慮以下代碼段:

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可以用非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在第一種情況下被忽略而在第二種情況下則不然?

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)

在重載解析期間, constvolatile指定的參數是重要的,除非它們出現在參數類型規范的最外層。 從C ++標准,§13.1.3.4:

僅存在或不存在const和/或volatile的參數聲明是等效的。 也就是說,在確定聲明,定義或調用哪個函數時,將忽略每個參數類型的const和volatile類型說明符。 [例如:

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]以這種方式只忽略參數類型規范最外層的const和volatile類型說明符; 埋在參數類型規范中的const和volatile類型說明符很重要,可用於區分重載的函數聲明。 特別是,對於任何類型T,“指向T的指針”,“指向const T的指針”和“指向易失性T的指針”被認為是不同的參數類型,“對T的引用”,“對const T的引用”和“參考揮發性的T.”

為什么const在第一種情況下被忽略而在第二種情況下則不然?

在第一種情況下, const適用於參數本身,而在第二種情況下, const適用於指針對象,而不是指針本身。 const指針指向const的指針不是一回事。

在第二種情況下,指向const的指針和指向非const的指針是不同的,可以接受重載。 如果你使指針本身為const ,即int* const p vs int* p ,你將獲得與第一種情況相同的結果。

因為當你宣布

void foo(const int n)
{
}

const修飾符所做的就是阻止在foo()函數中修改n 這個foo()函數的參數仍然是一個int const修飾符不會修改參數的類型。 所以兩者

void foo(int n)

void foo(const int n)

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

但是,之間存在差異

void foo(const int *p)

void foo(int *p)

一個是指向const整數的指針,另一個是指向可變整數的指針。 它們是不同的類型。

獎金回答:

void foo(int *p)

void foo(int * const p)

具有相同的參數類型。 兩個函數的參數都是指向int的指針。 除了第二個參數是const值,並且該函數不能修改它。

困惑了嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM