質問: 5;のやり方が出来てtest x(4);もできるということはわかるのですが、暗黙的型変換の防止とこれをする使いみちを教えてほしいです。 ``` class test { private: int x; int y; public: int pri_x()const { return x; } int pri_y()const{ return y; } explicit test(int a):x(a){ } //test(int a):x(a){ } }; ```
回答: `explicit` を `test x=5;` と書けなくする機能だと思っているとそれ以上の理解に及ばないでしょう。 `explicit` は暗黙の型変換を禁止する機能です。 `test x=5;` は暗黙の型変換によって `test x=x(5);` とコンパイラによって勝手に変換され、これが容認できる文脈においては(詳細略)コンパイルが通ってしまいます。この「暗黙の型変換」すなわち、引数1個のコンストラクタ=型変換コンストラクタを暗黙に呼ぶことを禁止するのが `explicit` です。 ``` struct A { A(int) { } }; struct B { B(A) { } }; int main() { B b(1); } ``` はコンパイル通ってしまいます。 `B` のコンストラクタは `A` を引数とするものしかないのに、不自然だと思いませんか? (修辞疑問) この理由は `B b(1);` をコンパイラが `B b(A(1));` と翻訳してしまうからです。ここで暗黙的型変換が勝手に起動していることになります。 `B b(1);` をコンパイルエラーにしたいのであれば、この暗黙的型変換を禁ずればよいので `explicit A(int) { }` が解決策です。 `explicit B(A) { }` と書いても、今回期待している内容には至らないのはわかりますよね? 実際コード書いていると、この暗黙的型変換が勝手に起動して「エラーになるはずなのにならない」という現象がそこそこ発生します。型変換コンストラクタは原則 `explicit` にする、くらいの心構えでいるほうが後々のトラブルを防止できるでしょう。