2016-06-20 15 views
4

は、次のコードスニペットを考えてみましょう:機能(のconstポインタ)

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);  
} 

コンパイルエラー:const sが非constオブジェクトを初期化することができるので redefinition of 'void foo(int)'

、上記の動作は、合理的なようです。それは第二の場合にはfoo_ptrのためにそうではない、なぜ最初のケースでfooの二つの定義が同じとみなされた場合 - それは明確であるかもしれませんが、私の質問をされ

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' 
} 

:今、これを検討?つまり、なぜconstが最初のケースでは無視され、2番目のケースでは無視されるのでしょうか?第1の場合

+0

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

+0

ことデュープconst intとint signaturesが同じとみなされる理由を説明しますが、OPはこれを(最初の例のように)非常によく理解しています。なぜポインターの例に同じ問題がないのかについては触れていません。 – paxdiablo

答えて

0

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

第2の場合には、constが指示先ではなく、ポインタ自体のために修飾されている間、constは、パラメータ自体の修飾です。 Constポインタconstへのポインタは同じものではありません。

第2のケースでは、constへのポインタと非constへのポインタが異なり、オーバーロードに許容されます。ポインタ自体をconstにすると、int* const pint* pの対比で、1番目のケースと同じ結果になります。

0

あなたは

void foo(const int n) 
{ 
} 

を宣言するときconst修飾子が行うことすべてがfoo()関数内で変更されてからnを防ぐことですので。このfoo()関数のパラメータは、まだintです。 const修飾子は、パラメータの型を変更しません。だから、両方の

void foo(int n) 

void foo(const int n) 

intパラメータを取る関数です。それらの間の唯一の違いは、2番目のパラメータがそのパラメータを変更できないことです。最初のパラメータは、他の非constのように関数内の変数と同様に変更できます。

しかし、

void foo(const int *p) 

void foo(int *p) 

一方との間に差があるが、他の一つは可変整数へのポインタであり、const整数へのポインタです。彼らは異なるタイプです。

ボーナス答え:

両方

void foo(int *p) 

void foo(int * const p) 

は同じパラメータタイプを持っています。両方の関数のパラメータはintへのポインタです。 2番目のパラメータがconstの値であることを除いて、関数はそれを変更できません。

まだ混乱していませんか?

+0

したがって、関数が異なる型のものであると認識しているのではなく、パラメータの型が異なる場合、関数の定義は異なります。 – ibrahim5253

+0

多かれ少なかれtrue。型の "top"部分に適用されたときの 'const' /' volatile'修飾子は、実際にはパラメータ型に影響しません。 –

3
const int* p 

整数の定数ポインタないが、それは整数定数(即ち、[const int] * pなくconst [int * p])へのポインタです。 - pその場合には、整数を指している、あなたが変更することが許可されていないポインタである

初心者への冗長ように見えるが、実際にはないかもしれ
const int * const p; 

:あなたは時々のようなコードを参照してください理由はここにありますでもは変更できません。

したがって、2番目のケースで使用している2つの機能は、受け入れられるパラメータが異なるとみなされます。それはまた、iが最も確実にconst整数ではないので、2番目の関数を呼び出す理由です。

つまり、const-パラメーターを変更しても関数シグネチャーに関しては変更されませんが、ここで行っていることではありません。パラメータを「ポインタからintへ」から「const intへのポインタ」に変更するとが署名に影響します。 const、オーバーロードの解決中に

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

volatileパラメータが、彼らは、パラメータのの最も外側のレベルで発生した場合を除き、重要であるに指定しています

あなたの最初のコードスニペットに相当例の両方を提供していることになりますタイプ仕様。 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.”

関連する問題