#explicit って何?
単語としての意味、"explicit"="明示的"
プログラムのキーワードとしての意味、"explicit"=「暗黙的型変換」を防止する機能です。
これだけでは意味は分からないので少し詳しく機能の説明もします。
**"explicit"は構造体(struct)やクラス(class)のコンストラクタにつけることで「暗黙的型変換」**を防止するキーワードです。
※キーワード:入力すると色が変わる単語(staticとか)
使用する際は引数が1つのものに使います。
より詳しくプログラムを使用して説明します。
struct A {
A(int);
};
struct B {
B(A) { }
};
int main() {
B b(1);
return 0;
}
よく**"explicit"**の記事で見かける例です。
このコードで起きてる**「暗黙的型変換」**とは
B b(1);
// B b(A(1)); と変換されている
**b(1) = b(A(1))となっているのがダメだということです。
この変換を防止できるのが"explicit"です。
ではこの"explicit"**の効果がどのように及ぶのか、ここで頭を悩ませました。
struct A {
A(int) { }; // explicit A(int) で B b(1)を防止できる
};
struct B {
B(A) { }; // explicit B(A) では B b(1)を防止できない
};
上のコードのように答えは、**"explicit A(int)"**に使用すると型変換を防止できます。
ですが不思議なことがあります。
**"explicit B(A)"を行っても"B b(1)"**で止めることができません。
なぜ防げないのか、私が理解できなかったのは**"explicit"の型変換を防止するという機能を勘違いしていたからです。
最初、私は"explicit"**の効果を
explicit A(int) の explicit A( INT ) , intの引数の変換を防ぐと思っていました。
しかし、**"explicit"**の防止する機能の動きが違うため理解ができませんでした。
struct A {
explicit A(int);
};
struct B {
B(A) { }
};
int main() {
// B b(1); エラー:1 を A(int) の型へ変換できないため
return 0;
}
上のコードだけだとまだ勘違いしてしまいますね。
int main() {
// B b(1); エラー:1 を A(int) の型へ変換できないため
// A a = 1; エラー:1 を A(int) の型へ変換できないため
return 0;
}
この一文を追加したらどうでしょう?
**"explicit"**は引数の型変換ではなく、コンストラクタ初期化やコピー初期化を防止する機能になります。
1 などの変数を 今回は "A(int)" に変換できなくしているわけです。
つまり、explicit B(A) で B b(1) が止められないのは
**explicit B(A)**は B(A) の型変換を防ぐことはできても A(int) の型変換は防げないのです。
それでは、今回の説明は以上です。