C++: 明示的なキーワード

C++ の明示的なキーワードは、パラメーターが 1 つだけあるクラス コンストラクターを変更する場合にのみ使用できます。その機能は、コンストラクターが暗黙的ではなく明示的であることを示すことです。これに対応する別のキーワードは暗黙的です。つまり、クラス コンストラクターは隠蔽され、宣言されます。デフォルトでは暗黙的に。

それでは、明示的に宣言されたコンストラクターと暗黙的に宣言されたコンストラクターの違いは何でしょうか?次の例を見てみましょう。

class CxString  // 没有使用explicit关键字的类声明, 即默认为隐式声明  
{  
public:  
    char *_pstr;  
    int _size;  
    CxString(int size)  
    {  
        _size = size;                // string的预设大小  
        _pstr = malloc(size + 1);    // 分配string的内存  
        memset(_pstr, 0, size + 1);  
    }  
    CxString(const char *p)  
    {  
        int size = strlen(p);  
        _pstr = malloc(size + 1);    // 分配string的内存  
        strcpy(_pstr, p);            // 复制字符串  
        _size = strlen(_pstr);  
    }  
    // 析构函数这里不讨论, 省略...  
};  
  
    // 下面是调用:  
    CxString string1(24);     // 这样是OK的, 为CxString预分配24字节的大小的内存  
    CxString string2 = 10;    // 这样是OK的, 为CxString预分配10字节的大小的内存  
    CxString string3;         // 这样是不行的, 因为没有默认构造函数, 错误为: “CxString”: 没有合适的默认构造函数可用  
    CxString string4("aaaa"); // 这样是OK的  
    CxString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)  
    CxString string6 = 'c';   // 这样也是OK的, 其实调用的是CxString(int size), 且size等于'c'的ascii码  
    string1 = 2;              // 这样也是OK的, 为CxString预分配2字节的大小的内存  
    string2 = 3;              // 这样也是OK的, 为CxString预分配3字节的大小的内存  
    string3 = string1;        // 这样也是OK的, 至少编译是没问题的, free释放_pstr内存指针的时候可能会报错, 完整的代码必须重载运算符"=", 并在其中处理内存释放

ここに画像の説明を挿入

上記のコードでは、なぜ「CxString string2 = 10;」という文が可能なのでしょうか?

C++ では、コンストラクターのパラメーターが 1 つだけの場合、コンパイル時にデフォルトの変換操作が行われます。つまり、コンストラクターのデータ型に対応するデータをこのクラスのオブジェクトに変換します。つまり、コード「CxString string2 = 10;」では、コンパイラは整数を CxString クラス オブジェクトに自動的に変換します。これは実際には次の操作と同等です。

CxString string2(10);  
// 或如下代码
CxString temp(10);  
CxString string2 = temp;  

ただし、上記のコードの _size は文字列メモリ割り当てのサイズを表すため、呼び出しの 2 番目の文「CxString string2 = 10;」と 6 番目の文「CxString string6 = 'c';」は平凡に見えますが、簡単です。戸惑う。この使用を防ぐ方法はありますか? 答えは、明示的なキーワードを使用することです。上記のコードを次のように変更してみましょう。

class CxString  // 使用关键字explicit的类声明, 显示转换  
{
    
      
public:  
    char *_pstr;  
    int _size;  
    explicit CxString(int size)  
    {
    
      
        _size = size;  
        // 代码同上, 省略...  
    }  
    CxString(const char *p)  
    {
    
      
        // 代码同上, 省略...  
    }  
};  
  
    // 下面是调用:  
    CxString string1(24);     // 这样是OK的  
    CxString string2 = 10;    // 这样是不行的, 因为explicit关键字取消了隐式转换  
    CxString string3;         // 这样是不行的, 因为没有默认构造函数  
    CxString string4("aaaa"); // 这样是OK的  
    CxString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)  
    CxString string6 = 'c';   // 这样是不行的, 其实调用的是CxString(int size), 且size等于'c'的ascii码, 但explicit关键字取消了隐式转换  
    string1 = 2;              // 这样也是不行的, 因为取消了隐式转换  
    string2 = 3;              // 这样也是不行的, 因为取消了隐式转换  
    string3 = string1;        // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载 

ここに画像の説明を挿入

明示的なキーワードの役割は、クラス コンストラクターの暗黙的な自動変換を防ぐことです。

前述したように、explicit キーワードはパラメーターが 1 つあるクラス コンストラクターに対してのみ有効です。クラス コンストラクターのパラメーターが 2 以上の場合、暗黙的な変換は行われないため、explicit キーワードは無効です。例えば:

class CxString  // explicit关键字在类构造函数参数大于或等于两个时无效  
{
    
      
public:  
    char *_pstr;  
    int _age;  
    int _size;  
    explicit CxString(int age, int size)  
    {
    
      
        _age = age;  
        _size = size;  
        // 代码同上, 省略...  
    }  
    CxString(const char *p)  
    {
    
      
        // 代码同上, 省略...  
    }  
};  
  
    // 这个时候有没有explicit关键字都是一样的  

ただし、例外があり、最初のパラメータを除くすべてのパラメータがデフォルト値を持つ場合でも、明示的なキーワードは引き続き有効です。このとき、コンストラクタを呼び出すときに渡されるパラメータは 1 つだけであり、これは 1 つのパラメータのみに相当します。この例のクラス コンストラクターは次のとおりです。

class CxString  // 使用关键字explicit声明  
{
    
      
public:  
    int _age;  
    int _size;  
    explicit CxString(int age, int size = 0)  
    {
    
      
        _age = age;  
        _size = size;  
        // 代码同上, 省略...  
    }  
    CxString(const char *p)  
    {
    
      
        // 代码同上, 省略...  
    }  
};  
  
    // 下面是调用:  
    CxString string1(24);     // 这样是OK的  
    CxString string2 = 10;    // 这样是不行的, 因为explicit关键字取消了隐式转换  
    CxString string3;         // 这样是不行的, 因为没有默认构造函数  
    string1 = 2;              // 这样也是不行的, 因为取消了隐式转换  
    string2 = 3;              // 这样也是不行的, 因为取消了隐式转换  
    string3 = string1;        // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载

概要:
明示的なキーワードは、クラス内の単一引数コンストラクターの前でのみ使用する必要があります。引数なしのコンストラクターと複数引数のコンストラクターは常に明示的に呼び出されるため、この場合、コンストラクターの前に明示的に追加することは無意味です。

Google の C++ 仕様では、明示的な利点は、時期尚早な型変換を回避できることであり、欠点はないと述べています。したがって、Google は、すべての単一パラメータのコンストラクタを表示する必要があることに同意します。他のクラスの透過的なラッパーであるクラスなど、コピー コンストラクタを明示的に宣言できないケースはごくわずかです。
効果的な C++ は次のように述べています: 明示的として宣言されたコンストラクターは、通常、明示的でない兄弟よりも人気があります。これらは、コンパイラーが意図しない (そして多くの場合意図しない) 型変換を実行することを禁止するためです。コンストラクターを暗黙的な型変換に使用できるようにする正当な理由がない限り、それを明示的に宣言し、全員が同じポリシーに従うことを奨励します。

おすすめ

転載: blog.csdn.net/crossoverpptx/article/details/129861992