2013-01-09 7 views
6

可能性の重複:
Difference between const declarations in C++constキーワード位置

#include <iostream> 

class Bar{}; 

void foo(const Bar x){} //l5 
void foo(Bar x){}  //l6 
void foo(Bar const x){} //l7 

////pointer functions 

void foo(const Bar* x){} //l11 
void foo(Bar* x){}  //l12 
void foo(Bar* const x){} //l13 

コンパイラ出力:(長い話を短くl5l6l7紛争;だけl12l13紛争)

untitled.cpp:6:6: error: redefinition of ‘void foo(Bar)’ 
untitled.cpp:5:6: error: ‘void foo(Bar)’ previously defined here 
untitled.cpp:7:6: error: redefinition of ‘void foo(Bar)’ 
untitled.cpp:5:6: error: ‘void foo(Bar)’ previously defined here 
untitled.cpp:13:6: error: redefinition of ‘void foo(Bar*)’ 
untitled.cpp:12:6: error: ‘void foo(Bar*)’ previously defined here 

何が起こっていますか?

  1. 宣言のそれぞれの意味は何ですか
  2. なぜ、すべての3つの宣言オブジェクト機能との競合だけで2ポインタ機能付き?
  3. l12constキーワードが含まれていないにもかかわらず、その競合がl12l13との間にある手の込んだしてください
  4. 本当に申し訳ありませんかの些細な質問
  5. あなたが前に、またはタイプ名の後のconstを置くかどうかは関係ありません

答えて

5

"問題"は、パラメータの値のネスが過負荷に関与していないことです。

まず、Bar constconst Barはすでに同じ意味であるため、自動的に問題が発生します。しかし、関数のパラメータとしてconstはオーバーロードには適用されないので、関数のBarも同じように見えます。パラメータメーターのconstは、関数本体で変更するつもりはないことをコンパイラーに通知します。

同じ理由で、Bar*Bar* constが同じに扱われますconstは、パラメータの値に適用されます(指さいないものを)し、過負荷に参加していないので、あなたは、同じ機能を定義しました。

一方、const Bar*は全く異なることを意味します。constオブジェクト(タイプBar)への非constポインタ。タイプが異なるので、オーバーロードに関与し、その機能をユニークにすることができます。

1

15と17は同じパラメータ引数リストを持ちます。
これらの2つの関数は同じプロトタイプを持つとみなされ、重複しています。

機能#1

void foo(const int x) { 
return; 
} 

機能#2 - 重複パラメータ引数リスト

void foo(int const x) { 
return; 
} 

のconstの位置は、あなたが持っている例では15と17と同じです。

どちらかがウィキペディアによると動作します:

http://en.wikipedia.org/wiki/Const-correctness

+0

最初の文章:この特定の文脈では、コンパイラには関係ありません。しかし、一般的に、 'const'は先行するものを変更し、' const'を変更した後に体系的に(const intではなく 'int const')、コードを読みやすくします。 –

0

最初の3が競合を作成する理由は、コンパイラがどのような場合に使用するように機能しているかを把握することはできませんということです。 foo(BarObject);を呼び出すと、BarObjectconstと宣言されているかどうかにかかわらず、コンパイラはそれらのいずれかを使用できます。コンパイラは]11をピックアップしますfoo(BarPointer);BarPointerconst Bar* BarPointer;として宣言された場合には、オブジェクトが渡したときに機能(ない場合には変更されませんし指さ保証するからあなたは、呼び出しポインタなどのパラメータを持つものでしかし

最初の3つの値と同様)。 constでない場合は、]12または]13を呼び出す必要があるかどうかはわかりません。Bar* const xの意味は、「xはパラメータとして渡されたもの以外のものを指すことはできません」です。これは発信者に関係ありません。宣言に

小参照:基本的に

const Bar x // x is an immutable copy of the original parameter. 
Bar const x // same as above and gets compiled, but cdecl says it is a syntax error. 

const Bar* x // x points to an object that can't be changed. 
Bar* const x // x can't point to any other object than the parameter passed. 
0

、C++コピーの値は関数を呼び出すときので、発信者の観点から最初の三つを区別するものは何もありません。 (呼び出し元は、関数がそれ自身の値を変更できないことを知っています。したがって、関数のパラメータは、呼び出し元の観点から見ても暗黙のうちに常に一定です)。

しかし、ポインターについて言えば、定数へのポインターと非定数へのポインターを渡すと、呼び出し元には違いがあります。これがl11とl12が矛盾しない理由です。

これらは両方ともBar *へのポインタである(1つはconstポインタであり、1つはそうではないので、l5-17と同じ問題、呼び出し元との違いはありません)。

この最後の点は少し難しいかもしれ - int const *aconst int *aと同じであるが、これらint * const a同じではないことに注意して、最初の二つは一定intへのポインタであり、他方はに対して一定のポインタでありますint(つまり、ポインタの値は後で変更できません)。両方がxBarタイプであり、それはconstと言うので

0
void foo(const Bar x){} 
void foo(Bar const x){} 

上記の二つは同一です。

void foo(Bar x){} 

上記2とこの1つの競合xconstであるか、あなたの関数の実装の詳細であり、関数のシグネチャからコンパイラによって破棄されたか否かをので。したがって、すべての3つの関数は、void foo(Bar x)という同じ署名を持つことになります。

void foo(Bar* x){} 
void foo(Bar* const x){} 

これは前のケースと同様です。ポインタxconstであることを示しています。つまり、xを関数内の他のものにリピートしません。両方の場合において、xが指すBarオブジェクトは、constではありません。したがって、xという数字は、この機能の実装の詳細です。ここで

void foo(const Bar* x){} 

あなたはconstあるBarオブジェクトにそのxポイントを示しています。これは前の2つのケースと異なり、矛盾はありません。

0

最初の3つの機能の場合 - constは、によって転送された変数の場合、オーバーロードの解像度には関係ありません。スタック上に作成された引数のコピー。このコピーが外部(呼び出し元)の観点から変更されているかどうかは分かりません。機能自体(内部)にとって重要です。

ポインタベースの関数の場合、コピーはスタック上に作成されず、外部(呼び出し側)の観点から関数が引数の値を変更するかどうかを意味するため、関数のオーバーロード解決の重要な部分です。 Barからxポインタ、と私は変更される可能性がありxによって指さこのBar値がある:最後の二つの機能については

は、コンパイラに言います。しかし、最初のケースでは、ポインタxの値を、別のケースとは反対の(例えば、Barを指して)変更することができます。そして、ここでは最初の状況です。ポインタ自体のコピーはスタック上にあり、関数内で変更された場合にはオーバーロードの解決には意味がありません。

関連する問題