質問
最近傍クエリを実行するコードに取り組んでいます。ユーザーが検索でデータをクエリする方法の基礎となる 2 つの単純なアイデアがあります。
- 空間内の特定の点に最も近い N 点。
- 指定された距離内のすべてのポイント。
私のコードでは、ポイントは PointList に入れられます。PointList は、検索で見つかったポイントを追跡する役割を持つコンテナーです。
現在、PointList オブジェクトにはコンストラクターが 1 つあります。
PointList( unsigned int maxvals ); // #1
次に追加する 2 つのコンストラクターは次のとおりです。
PointList( float maxdist ); // #2
PointList( unsigned int maxvals, float maxdist ); // #3
私の質問は次のとおりです。ユーザーとC ++コンパイラが正しいものを生成するようにするにはどうすればよいですか PointListのコンストラクタであり、コンストラクタ1と2を区別しますか?#3を実装して、任意の大きな定義を行う定数を提供する必要があります maxvals と maxdist の値別の代替案としては、リストにポイントを追加するロジックを制御する軽量オブジェクトの別のシステムを作成することも考えられますが、このような単純なアイデアではやりすぎのように感じられます。
私はこれをユーザーに対して透明性を持たせることに真剣に取り組んでいます。ユーザーのほとんどは正式な教育を受けずに C++ を学んだ科学者です。ありがとう!
解決
整数型のオーバーロード解決は 2 つのカテゴリで発生します。これらは非常に大まかに次のように要約できます。
- プロモーション:これは、より小さい型からの変換です。
int
にint
またはunsigned int
, 、どうかに応じてint
ソースタイプのすべての値を保存できます。 - 変換:これは、任意の整数型から別の整数型への変換です。
同様に、浮動小数点型の変換は 2 つのカテゴリで発生します
- プロモーション:これはからの変換です
float
にdouble
- 変換:これは、任意の浮動小数点型から別の浮動小数点型への変換です。
また、整数から浮動小数点数への変換、またはその逆の変換もあります。これはプロモーションではなくコンバージョンとしてランク付けされます。プロモーションはコンバージョンよりもランク付けが高く、プロモーションのみが必要な場合はそのケースが優先されます。したがって、次のコンストラクターを使用できます。
PointList( int maxVals );
PointList( unsigned int maxVals );
PointList( long maxVals );
PointList( unsigned long maxVals );
PointList( double maxDist );
PointList( long double maxDist );
整数型の場合、これはコンストラクターの最初のグループを選択する必要があります。また、浮動小数点型の場合は、コンストラクターの 2 番目のグループを選択する必要があります。元の 2 つのコンストラクターでは、間であいまいさが簡単に生じる可能性があります。 float
そして unsigned int
, 、を渡すと、 int
, 、 例えば。もう 1 つの 2 つの引数コンストラクターについては、必要に応じて独自のソリューションを使用できます。
そうは言っても、パラメータの意味の型を決定するのは非常に不安定だと思うので、私はファクトリ関数も使用します。ほとんどの人は、次の結果が次の結果と等しいと期待するでしょう。
PointList p(floor(1.5));
PointList u((int)1.5);
しかし、それは異なる状況をもたらすでしょう。
他のヒント
コンストラクターの代わりにファクトリ メソッドを使用してみてはいかがでしょうか?ファクトリ メソッドには、名前をカスタマイズできるという利点があります。
static PointList createNearestValues(unsigned int maxvals) {}
static PointList createByDistance(float maxdist) {}
使用を検討してください 真の typedef. 。クライアント コード側では少し手間がかかりますが、正確性は保証されています。
最初の場合は PointList(10) を呼び出し、2 番目の場合は PointList(10f) を呼び出します。
2 番目の場合は、10.0 を使用することもできます。
コンストラクター #1 と #2 が存在する場合、挿入した値が float または int の場合は正しいコンストラクターが呼び出され、変換は行われません。したがって、呼び出しに使用する番号のタイプを必ず明示的にするようにしてください(つまり、1fと1)。コンストラクター #3 は実際には必要ではなく、コードのユーザーを混乱させるだけであるため、あまり選択肢にはならないようです。いずれかの数値のデフォルト値が必要な場合は、使用できます
PointList(int max, float max=VALUE)
そして
PointList(float max, int max=VALUE)
また:これは、コードの可読性の点で、コードよりも害があるようです。
これはよく読む必要があります 過負荷の解決.
間違いなく使います 明示的な コンストラクター。この例では、符号なし整数は暗黙的に変換されません。
class A
{
public:
explicit A(float f){}
explicit A(int i){}
};
void test(){
unsigned int uinteger(0);
A a1(uinteger); //Fails, does not allow implicit conversions
A a2((float)uinteger); //OK, explicit conversion
float f(0.0);
A a3(f); //OK
int integer(0);
A a4(integer); //OK
}
エラー メッセージは非常に理解しやすいものです。
: error C2668: 'A::A' : ambiguous call to overloaded function
: could be 'A::A(int)'
: or 'A::A(float)'