explicit

http://www.geocities.jp/ky_webid/cpp/language/024.html

キャスト絡みでもうひとつ。explicitについてです。

これはクラスのコンストラクタを宣言する際に使うことができます。

まずはexplicitの前に以下の実装を見てください。

#include <iostream>
using namespace std;

class CSample {
public:
    int m_num;
    CSample (int num) {
        m_num = num;
    }
};

int main () {
    CSample obj = 100;
    
    cout << obj.m_num << endl;
    return 0;
}
$ main
100

obj変数に対して100を代入しています。

これは結局のところ

CSample obj(100);

とやってることは同じなんですが、代入式で書いた場合、実は100というint型からCSample型への暗黙の型変換が行われているのです。

この暗黙の型変換は、そのクラスのコンストラクタの第一引数と、代入する値が一致していた場合のみ有効となります。

なのでもちろんコンストラクタの引数が二つ以上あったり、型が違っていたりするとコンパイルエラーになります。

で話を最初に戻してexplicitをコンストラクタに指定しておくと、この暗黙の型変換をできないように設定することが可能というわけなのです。

試してみます。

#include <iostream>
using namespace std;

class CSample {
public:
    int m_num;
    explicit CSample (int num) {
        m_num = num;
    }
};

int main () {
    CSample obj = 100;
    
    cout << obj.m_num << endl;
    return 0;
}
$ cl /W4 /EHs main.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(13) : error C2440: '初期化中' : 'int' から 'CSample' に変換できません。

        class 'CSample' のコンストラクタが 'explicit' と宣言されています。

見事にコンパイルエラーになりましたね。

C++って○○させない堅牢な記述ができて、でもそれに対する抜け穴を用意してて、更に○○させない記述ができたりして、更に更に・・・、みたいな感じですよね。

そこが面倒臭くも面白い感じで楽しいところなんですけどね(笑