C++でexplicitの使い方

はじめんい
C++でESP32開発をしている際に、見慣れない
explicit
にであったので調べてみました。
- explicitの意味: はっきりと述べられた、曖昧さのない、明確な、明白な
だそうです。下記のようなクラスを作っていたところ、BluetoothHelperのコンストラクタ部分で、explicit
を付けるようにサジェストされました。
class BluetoothHelper {
public:
explicit BluetoothHelper(const String& deviceName);
bool on();
void off();
void send(const String& message);
();
String waitForResponse...
};
気になって調べたので、次にまとめます。
explicitの使い方
C++におけるexplicit
キーワードは、コンストラクタが暗黙的な型変換から呼び出されることを防ぐために使用されます。コンストラクタが一つの引数を取る場合(または全ての引数にデフォルト値がある場合)、そのコンストラクタは変換コンストラクタとして機能し、コンパイラによって暗黙的にその型への変換を行う場合があります。
つまり、引数がひとつだけのコンストラクタを持つクラスだと、「暗黙的な型変換」という特別な動作をしてしまうことのようです。explicit
キーワードをコンストラクタに付けることで、そのコンストラクタを通じた暗黙的な型変換を禁止し、型変換が意図されたものであることを明示的にできます。
explicit
がない場合
class MyClass {
public:
(int x) { ... } // このコンストラクタは暗黙的な型変換を許可する
MyClass};
この場合、MyClass
のオブジェクトはint
型の値から暗黙的に生成することができます。
= 10; // intからMyClassへの暗黙的な型変換が行われる MyClass obj
使い方によっては便利そうですが、今回の場合はちょっと意図していない使い方ですね。
explicit
がある場合
class MyClass {
public:
explicit MyClass(int x) { ... } // このコンストラクタは暗黙的な型変換を禁止する
};
この場合、MyClass
のオブジェクトをint
型の値から生成するには、明示的な型変換が必要になります。つまり先ほどのような「暗黙的な型変換」の書き方はエラーになります。
= 10; // エラー: 暗黙的な型変換は禁止されている
MyClass obj (10); // OK: 明示的なコンストラクタ呼び出し
MyClass obj= MyClass(10); // OK: 明示的な型変換 MyClass obj
これで普段通り、意図した実装になりました。
explicit
のメリット
メリット | 説明 |
---|---|
型安全性の向上 | プログラマが意図しない型変換を防ぎ、 バグの可能性を減らします。 |
コードの意図の明確化 | コンストラクタを通じた型変換が 意図的にのみ行われるようにし、 コードの読み手にその意図を明確に伝えます。 |
まとめ
「暗黙的な型変換」は、特に大きなコードベースや複数人での開発プロジェクトにおいて、意図しないバグの原因となることがあります。ですからexplicit
キーワードを使用して、バグを未然に防ぎましょう。