Palabra clave explícita en C ++

La palabra clave explícita en C ++ se utiliza para modificar el constructor de la clase con un solo parámetro. Su función es indicar que el constructor es explícito, no implícito. Otra palabra clave que le corresponde es implícita, que significa oculto de.
El constructor de la clase se declara implícito de forma predeterminada.
Último ejemplo:

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内存指针的时候可能会报错, 完整的代码必须重载运算符"=", 并在其中处理内存释放

En el código anterior, ¿por qué la oración "CxString string2 = 10;" está bien? En C ++, si el constructor tiene solo un parámetro, habrá una operación de conversión predeterminada al compilar: Los datos correspondientes al tipo de datos del constructor se convierte a este tipo de objeto. Es decir, "CxString string2 = 10;" Este código, el compilador convierte automáticamente el tipo entero al objeto CxString, que en realidad es equivalente a la siguiente operación:

CxString string2(10);  
或  
CxString temp(10);  
CxString string2 = temp;  

Sin embargo, el _size en el código anterior representa el tamaño de la asignación de memoria de la cadena, por lo que la segunda oración de la llamada "CxString string2 = 10;" y la sexta oración "CxString string6 = 'c';" son anodinas y es fácil estar desconcertado.
¿Hay alguna forma de evitar este uso? La respuesta es utilizar la palabra clave explícita. Modifiquemos el código anterior de la siguiente manera:

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;        // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载

La función de la palabra clave explícita es evitar la conversión automática implícita del constructor de la clase.

Como se mencionó anteriormente, la palabra clave explícita solo es válida para un constructor de clase con un parámetro. Si los parámetros del constructor de clase son mayores o iguales a dos, no se producirá ninguna conversión implícita, por lo que la palabra clave explícita no es válida. P.ej:

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关键字都是一样的

Sin embargo, hay una excepción, es decir, cuando otros parámetros, excepto el primer parámetro, tienen valores predeterminados, la palabra clave explícita sigue siendo válida. En este momento, cuando se llama al constructor, solo se pasa un parámetro, que es equivalente a solo un parámetro. El constructor de la clase, los ejemplos son los siguientes:

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;        // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载

Lo anterior es una introducción detallada a la palabra clave explícita de C ++.

para resumir

La palabra clave explícita solo debe usarse delante del constructor de un solo argumento en la clase. Dado que el constructor sin parámetros y el constructor multiparámetro siempre se llaman explícitamente, no tiene sentido agregar explícito antes del constructor en este caso.

La ventaja de lo explícito mencionado en la especificación C ++ de Google es que puede evitar la conversión de tipos inoportuna y no hay desventajas. Por lo tanto, Google acepta que se deben mostrar todos los constructores de un solo parámetro. Solo en casos excepcionales, el constructor de copia no se puede declarar como explícito. Por ejemplo, una clase que sirve como envoltorio transparente para otras clases.

C ++ efectivo dice: Los constructores declarados como explícitos suelen ser más populares que sus hermanos no explícitos. Porque prohíben al compilador realizar conversiones de tipo inesperadas (y a menudo no esperadas). A menos que tenga una buena razón para permitir que el constructor se use para la conversión de tipo implícita, lo declararé explícito y alentaré a todos a seguir la misma política.

Proporcione el enlace original: https://www.cnblogs.com/rednodel/p/9299251.html

Supongo que te gusta

Origin blog.csdn.net/qq_24649627/article/details/111217849
Recomendado
Clasificación