48088


explicitの明示的コンストラクタなの使い方なのですが、引数が一個の時だけ使えて  
暗黙的型変換を防止できできてmain.cppのmain関数で test x = 5;という書き方がエラーになって。text
x(4);はできる。。explicitを書かないとtest x = 5;のやり方が出来てtest
x(4);もできるということはわかるのですが、暗黙的型変換の防止とこれをする使いみちを教えてほしいです。

[code]

                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){ }
    
            };
    
[/code]


CC BY-SA 4.0
2018-09-04T17:31:28.680
48085
2018-09-09T04:20:00.187
question
c++
c++,explicitの使い道について知りたい


`explicit` を `test x=5;` と書けなくする機能だと思っているとそれ以上の理解に及ばないでしょう。 `explicit`
は暗黙の型変換を禁止する機能です。

`test x=5;` は暗黙の型変換によって `test x=x(5);`
とコンパイラによって勝手に変換され、これが容認できる文脈においては（詳細略）コンパイルが通ってしまいます。この「暗黙の型変換」すなわち、引数１個のコンストラクタ＝型変換コンストラクタを暗黙に呼ぶことを禁止するのが
`explicit` です。

[code]

    struct A {
        A(int) { }
    };
    struct B {
        B(A) { }
    };
    int main() {
        B b(1);
    }
    
[/code]

はコンパイル通ってしまいます。 `B` のコンストラクタは `A` を引数とするものしかないのに、不自然だと思いませんか？ （修辞疑問）

この理由は `B b(1);` をコンパイラが `B b(A(1));` と翻訳してしまうからです。ここで暗黙的型変換が勝手に起動していることになります。
`B b(1);` をコンパイルエラーにしたいのであれば、この暗黙的型変換を禁ずればよいので `explicit A(int) { }` が解決策です。

`explicit B(A) { }` と書いても、今回期待している内容には至らないのはわかりますよね？

実際コード書いていると、この暗黙的型変換が勝手に起動して「エラーになるはずなのにならない」という現象がそこそこ発生します。型変換コンストラクタは原則
`explicit` にする、くらいの心構えでいるほうが後々のトラブルを防止できるでしょう。


CC BY-SA 4.0
2018-09-04T23:32:00.257
48088
2018-09-05T11:42:17.000
2018-09-05T11:42:17.000
8589
8589
48085
answer


以下のような場合等に`explicit`接頭辞を付けて暗黙の型変換を抑止します。

  * ユーザーが使用を誤る可能性が高い
  * 暗黙の型変換が便利でない
  * 暗黙の型変換が直観的でない

例えば、`std::vector`の[コンストラクター](https://cpprefjp.github.io/reference/vector/op_constructor.html)の一つに`explicit
vector(size_type n)`（省略可能な引数付のも含む）がありますが、これに`explicit`接頭辞を付けていないとどうなるでしょうか。  
`vector(size_type n)`は、「n 個の T() で初期化された要素を保持した vector
オブジェクトを構築する」コンストラクターですので、以下のようにすると5つの`0`を保持したオブジェクト`vec`が生成されます。

[code]

    std::vector<int> vec(5);
    
[/code]

これは、個人的にはわかり易い仕様ではないと思いますが、実行効率が良いと思われるため許容できる仕様です。  
一方で、以下のように書いた場合、オブジェクト`vec`がどういう状態になるか容易に想像できるでしょうか？

[code]

    std::vector<int> vec;
    vec = 5;
    
[/code]

（私には）直観的には、`5`という一つの要素を保持したオブジェクト`vec`になりそうに見えますが、実際には先の例と同じく5つの`0`を保持したオブジェクト`vec`になってしまいます。  
また、意図して5つの`0`を保持したオブジェクト`vec`にしたい場合は以下のように書けば良いので、あまり不便では無いように思えます。

[code]

    std::vector<int> vec;
    vec = std::vector<int>(5);
    
[/code]

`std::vector`の設計者達も以上のような事を考慮した結果、`vector(size_type
n)`に`explicit`接頭辞を付けたのだと思われます。

* * *

ちなみに、C++の生みの親であるBjarne
Stroustrup氏の著書「C++の設計と進化」で、`explicit`接頭辞そのものの導入の発端として、`vector(size_type
n)`の事が語られています。


CC BY-SA 4.0
2018-09-09T04:20:00.187
48232
2018-09-09T04:20:00.187
7291
48085
answer