C++には、引数の型が期待されるものでない場合に、パラメーターの型の一致するコンストラクターを自動的に呼び出す機能があります(適切な名前がわかりません)。
これの非常に基本的な例は、std::string
引数を持つconst char*
を期待する関数の呼び出しです。コンパイラーは、適切なstd::string
コンストラクターを呼び出すコードを自動的に生成します。
思ったより読みやすさは悪いのでしょうか?
次に例を示します。
class Texture {
public:
Texture(const std::string& imageFile);
};
class Renderer {
public:
void Draw(const Texture& texture);
};
Renderer renderer;
std::string path = "foo.png";
renderer.Draw(path);
それでいいですか?それとも行き過ぎですか?私がそれをするべきではない場合、どういうわけかClangまたはGCCにそれについて警告させることができますか?
これは、変換コンストラクター(または、暗黙のコンストラクターまたは暗黙の変換)と呼ばれます。
これが発生したときに警告するコンパイル時の切り替えについては知りませんが、簡単に防ぐことができます。 explicit
キーワードを使用するだけです。
class Texture {
public:
explicit Texture(const std::string& imageFile);
};
コンストラクタを変換するかどうかは良い考えです。
暗黙的な変換が意味をなす状況:
std::string
など、暗黙的に変換できるconst char *
と同じ概念を反映している)ため、暗黙的な変換は理にかなっています。暗黙的な変換があまり意味をなさない状況:
クラスFlagList { FlagList(int initial_size); }; void SetFlags(const FlagList&flag_list); int main(){ //これでコンパイルされます、まったく明らかではありませんが、 //何をしているか。 SetFlags(42); }
AnsiString
クラスは ない UnicodeからANSIへの変換では情報が失われる可能性があるため、UnicodeString
から暗黙的に構成します。参考文献:
これは回答というよりコメントですが、コメントを入れるには大きすぎます。
興味深いことに、g++
はそれをさせません:
#include <iostream>
#include <string>
class Texture {
public:
Texture(const std::string& imageFile)
{
std::cout << "Texture()" << std::endl;
}
};
class Renderer {
public:
void Draw(const Texture& texture)
{
std::cout << "Renderer.Draw()" << std::endl;
}
};
int main(int argc, char* argv[])
{
Renderer renderer;
renderer.Draw("foo.png");
return 0;
}
以下を生成します。
$ g++ -o Conversion.exe Conversion.cpp
Conversion.cpp: In function ‘int main(int, char**)’:
Conversion.cpp:23:25: error: no matching function for call to ‘Renderer::Draw(const char [8])’
Conversion.cpp:14:8: note: candidate is: void Renderer::Draw(const Texture&)
ただし、行を次のように変更した場合:
renderer.Draw(std::string("foo.png"));
その変換を実行します。
これは暗黙の型変換と呼ばれます。一般的に、それは不必要な繰り返しを抑制するので、良いことです。たとえば、std::string
バージョンのDraw
のために追加のコードを記述する必要はありません。また、Renderer
自体を変更せずにRenderer
の機能を拡張できるため、オープン/クローズの原則に従うのにも役立ちます。
一方、欠点がないわけではありません。一つには、議論がどこから来ているのかを理解するのが難しい場合があります。他の場合には、予期しない結果が生じることがあります。それがexplicit
キーワードの目的です。 Texture
コンストラクターに配置すると、暗黙的な型変換にそのコンストラクターを使用できなくなります。暗黙的な型変換についてグローバルに警告するメソッドは知りませんが、それはメソッドが存在しないという意味ではなく、gccに理解できないほど多くのオプションがあるということだけです。