En C++, si una clase tiene un constructor al que se puede llamar con un solo argumento, este constructor se convierte en un constructor de conversión porque dicho constructor permite la conversión automática a la clase que se está construyendo.
Problema:
Siempre que hay un constructor con un solo argumento y hay una función que toma un argumento del mismo tipo de clase pero cuando se llama a esta función usando un tipo de argumento igual al del constructor, en ese caso, se llama a la función exitosamente. Esto se debe a que el constructor convierte implícitamente el argumento al tipo de clase. El argumento se pasa al constructor y luego se ejecuta la función. Esto es algo que no esperaríamos.
A continuación se muestra el programa C++ que demuestra el problema anterior:
C++
// C++ program to implement // the above approach #include <iostream> using namespace std; // Defining the class class GfG { int data; public: // Constructor with single parameter GfG(int a) : data(a) { } // Default constructor GfG() {} // Defining function to print // the value of data member void display() { cout << "Value of data is: " << data; } }; // User-defined function that takes // object of class GfG as argument void func(GfG o) { o.display(); } // Driver code int main() { int var = 10; // Function gets called even if // int type argument is passed func(var); }
Value of data is: 10
Explicación:
En el código anterior, hay un constructor definido por el usuario que toma un argumento de tipo GFG (tipo de clase) y hay una función que también toma un argumento de tipo de clase. Cuando hay un intento de invocar la función pasando el parámetro de tipo int, en este caso, la función se llama con éxito. Esto sucede debido al constructor definido por el usuario. El valor int pasado a la función se convierte implícitamente en tipo de clase y el miembro de datos se inicializa con el valor del parámetro pasado (var).
Solución:
Para evitar este problema de conversión implícita es hacer explícito el constructor. A continuación se muestra el programa C++ para demostrar la solución al problema de conversión implícita:
C++
// C++ program to implement // the above approach #include <iostream> using namespace std; // Defining the class class GfG { int data; public: // Constructor with single parameter // declared explicit explicit GfG(int a) : data(a) { } // Default constructor GfG() {} // Function to print value // of data member void display() { cout << "Value of data is: " << data; } }; // User-defined function that takes // object of class GfG as argument void func(GfG o) { o.display(); } // Driver code int main() { int var = 10; // This function call results // in error func(var); }
Producción:
Inconveniente:
Este enfoque, sin embargo, tiene algunos inconvenientes. ¿Qué pasa si en el mismo programa el usuario realmente quiere convertir el tipo de datos int al tipo de datos de clase y asignar un valor int a un objeto de la clase? La siguiente asignación dará como resultado un error-
int var = 10; GfG obj = var; // This will result in error
Para resolver este problema, puede convertir explícitamente var a GfG y luego asignarlo a obj.
GfG obj = (GfG) var; // This works fine
A continuación se muestra el programa C++ para implementar el enfoque anterior:
C++
// C++ program to implement // the above approach #include <iostream> using namespace std; // Defining the class class GfG { int data; public: // Constructor with single parameter // declared explicit explicit GfG(int a) : data(a) { } // Default constructor GfG() {} // Function to print value // of data member void display() { cout << "Value of data is: " << data; } }; // User-defined function that takes // object of class GfG as argument void func(GfG o) { o.display(); } // Driver code int main() { int var = 10; // Explicitly converting var to // class (GfG) type GfG obj = (GfG)var; // Calling function with the // converted variable obj func(obj); }
Value of data is: 10
Consideremos un ejemplo más y analicemos qué sucede cuando lo explícito tampoco funciona.
C++
// C++ program to implement // the above approach #include <iostream> using namespace std; // Defining the class class GfG { private: string str; public: // Constructor with single parameter // declared explicit GfG(int a) { str.resize(a); } // Default constructor GfG(const char* string) { str = string; } // Function to print value // of data member void display() { cout << "String is: " << str << "\n"; } }; // User-defined function that takes // object of class GfG as argument void func(GfG o) { o.display(); } // Driver code int main() { // This line will compile and // will use GFG(int) GfG obj = 'x'; // Calling function with the // converted variable obj func(obj); return 0; }
Producción
String is:
Explicación:
en el ejemplo anterior, el usuario intenta inicializar una string con un valor char pero char es parte de la familia de enteros, por lo que la compilación usará el constructor GfG(int) para convertir implícitamente char a GfG. Esto producirá resultados inesperados.
Como se discutió anteriormente, una de las soluciones a este problema es usar la palabra clave explícita.
C++
// C++ program to implement // the above approach #include <iostream> using namespace std; // Defining the class class GfG { private: string str; public: // Constructor with single parameter // declared explicit explicit GfG(int a) { str.resize(a); } // Default constructor GfG(const char* string) { str = string; } // Function to print value // of data member void display() { cout << "String is: " << str << "\n"; } }; // User-defined function that takes // object of class GfG as argument void func(GfG o) { o.display(); } // Driver code int main() { // Compile-time error since // GfG(int) is explicit, so // nothing will match. GfG obj = 'x'; // Calling function with the // converted variable obj func(obj); return 0; }
Producción:
Explicación:
el programa anterior no compilará, ya que GfG(int) se hizo explícito y no se pudo encontrar un constructor de conversión adecuado para convertir implícitamente ‘x’ en GfG. Tenga en cuenta que las palabras clave explícitas solo pueden rechazar conversiones implícitas, el encasillamiento no se puede evitar usando la palabra clave explícita como se discutió anteriormente.
La palabra clave eliminar
Una solución parcial al problema anterior es crear un constructor privado GfG(char). A continuación se muestra el programa C++ para implementar este concepto:
C++
// C++ program to implement // the above approach #include <iostream> using namespace std; // Defining the class class GfG { private: string str; // Objects of type char cannot // be constructed from outside // the class GfG(char) { } public: // Constructor with single parameter // declared explicit explicit GfG(int a) { str.resize(a); } // Default constructor GfG(const char* string) { str = string; } // Function to print value // of data member void display() { cout << "String is: " << str << "\n"; } }; // User-defined function that takes // object of class GfG as argument void func(GfG o) { o.display(); } // Driver code int main() { // Compile-time error since // GfG(char) is private GfG obj = 'x'; // Calling function with the // converted variable obj func(obj); return 0; }
Producción:
Explicación:
En el código anterior, el constructor GfG(char) se hace privado. Esto ha impedido el acceso al constructor desde fuera de la clase, pero aún se puede usar dentro de la clase. La solución a este problema es utilizar la palabra clave delete.
Eliminar palabra clave:
a continuación se muestra el programa C++ para implementar el concepto de eliminar palabra clave:
C++
// C++ program to implement // the above approach #include <iostream> using namespace std; // Defining the class class GfG { private: string str; // Any use of this constructor // is an error GfG(char) = delete; public: // Constructor with single parameter // declared explicit explicit GfG(int a) { str.resize(a); } // Default constructor GfG(const char* string) { str = string; } // Function to print value // of data member void display() { cout << "String is: " << str << "\n"; } }; // User-defined function that takes // object of class GfG as argument void func(GfG o) { o.display(); } // Driver code int main() { // Compile-time error since // GfG(char) is deleted GfG obj = 'x'; // Calling function with the // converted variable obj func(obj); return 0; }
Producción:
Explicación:
cuando se elimina una función, cualquier uso de esa función es un error de tiempo de compilación.
Publicación traducida automáticamente
Artículo escrito por husain0803 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA