関数を呼び出す場合に好ましい間違った引数変換
-
20-08-2019 - |
質問
私はMSのVisual Cでプログラムを書いてい++ 6.0(はい、私はそれが古代の知っている、いや、私はアップグレードするためにできることは何もありません)。私は本当に奇妙だと思ういくつかの行動を見ています。私はこのように定義された2つのコンストラクタを持つクラスを持っています:
class MyClass
{
public:
explicit MyClass(bool bAbsolute = true, bool bLocation = false) : m_bAbsolute(bAbsolute), m_bLocation(bLocation) { ; }
MyClass(const RWCString& strPath, bool bLocation = false);
private:
bool m_bAbsolute;
bool m_bLocation;
};
私はこの構文を使用して、このクラスのインスタンスをインスタンス化する場合:MyClass("blah")
、それは最初のコンストラクタを呼び出します。あなたが見ることができるように、私はそれはそれをしないだろうことを期待...ないサイコロでそれにexplicit
キーワードを追加しました。 const char *
をとるコピーコンストラクタを持っているbool
への変換、上RWCString
するstrPath
からの変換を好むように見えます。それはなぜこれを行うのですか?私はこのような二つの可能な選択肢を考えると、それはそれは曖昧だと言うだろうことを前提としています。私はこれをやってからそれを防ぐために何ができますか?可能であれば、私はリテラルで多くを使用することになるだろうとして、明示的に<=>に<=>引数をキャストすることを避けるためにたいと思い、それは余分なタイピングの多く(プラス本当に簡単な間違いのです)作ります。
解決
コンストラクタが暗黙の型変換、単に受信者の一部ではないとして、明示的には、ここで助けにはなりません。
変換の優先順序を制御する方法はありませんが、あなたは*のconst char型を取った二コンストラクタを追加することができます。例えばます:
class MyClass
{
public:
MyClass(bool bAbsolute = true, bool bLocation = false);
MyClass(const RWCString& strPath, bool bLocation = false);
MyClass(const char* strPath, bool bLocation = false);
private:
bool m_bAbsolute;
bool m_bLocation;
};
他のヒント
アンドリュー・グラントは、ソリューションを提供します。私はなぜのそれはあなたがしようとしたように動作しません。あなたがをお伝えしたいと思います。あなたは、引数のための2つの実行可能な機能を持っている場合は、最高の引数と一致するものが呼ばれています。最初に、標準の変換を必要としながら、第二は、ユーザー定義の変換を必要とします。コンパイラは、第二の上に最初のを好む理由です。
; tはそれをキャスト維持したい、あなたがconstのchar型をとり、別のctorをしなければならないかもしれないと私には思える*
。私はおそらくこのような状況でどうなるのかです。
(わからない、なぜあなたは、その使用のほとんどのために渡していないタイプのctorのを作っている。)
編集ます:
私は
鉱山を入力している間に他の誰かがすでにこの投稿を見ますこれは文字列やブール値への参照を混同すべき理由わかりませんか?私は、BOOLとINTの問題を見てきました。
あなたは、最初のコンストラクタのデフォルト値を失うことができる - それは、このため、それはMyClass(デフォルトコンストラクタ作っていることもあります)、それはそれは引数と一致することができない場合、デフォルトでもある
あなたの選択肢は、明示的にCONST、char *を取るコンストラクタを追加します。
MyClass(const char* strPath, bool bLocation = false); // Thanks Andrew Grant!
それともん。
MyClass( string("blah") );
コンパイラは、本質的にブール値へのconstのchar *を作る方法を知っています。これは、MyClassのコンストラクタの第一引数の型のいずれかのために、あなたはそれを与えてくれたソースタイプを取るコンストラクタがあります、かどうかを調べて行かなければならない、またはそれが受け入れられるタイプにキャストできるかどうかあなたのMyClassのコンストラクタの第一引数の型のいずれかのコンストラクタのいずれか、または...よく、これが起こっている場所をあなたが見ると、それは最初の引数だけのためです。そのように狂気に位置しています。
explicit
キーワードは、
struct C { explicit C( int i ): m_i(i) {}; int m_i; };
C c = 10;//disallowed
C c( 2.5 ); // allowed
C ++は、あなたのケースで呼ばれるように何であるか、コンストラクタを決定する一連のルールを持っている - 私は私の頭の後ろから知らないが、あなたは直感的にデフォルト引数が曖昧に向けて導くことがわかります。
。あなたはを通して、これらのデフォルトを考える必要があります。
あなたはいくつかの静的な、という名前の、施工方法にフォールバックすることができます。それとも、(設計上の観点から、悪い選択ではない)別のクラスを使用することができます。いずれかの方法で、クライアントコードを使用するコンストラクタ決定させます。
struct C {
static C fromString( const char* s, const bool b = true );
static C fromBools( const bool abs = true, const bool b = true );
};
または
struct CBase {
bool absolute;
bool location;
CBase( bool abs=true, bool loc=true );
};
struct CBaseFromPath {
// makes 'absolute' true if path is absolute
CBaseFromPath( const char* s, const bool loc );
};
それは本当に最初のコンストラクタを呼び出していることを特定のあなたがはありますか?あなたは、ハードコードされた文字列でそれを呼び出している、またはそれは#define
後ろに隠れていますか?あなたはの#defineは、あなたはそれが何を考えていることを確認していますか? (拡大プリプロセッサの出力を取得するために/ Efのオプションを指定してコンパイルしてみて、呼び出しは、あなたがそれを見て期待するように見えるかどうかを確認します。)
EDIT:このおよび他のコメントに基づいて、私の提案は、その実現可能であるconst char*.
のための別のコンストラクタを追加することです。