12.6. Conversión automática de tipos

En C y C++, si el compilador encuentra una expresión o una llamada a función que usa un tipo que no es el que se requiere, a menudo podrá realizar una conversión automática de tipos desde el tipo que tiene al tipo que necesita. En C++, puede conseguir este mismo efecto para los tipos definidos por el usuario creando funciones de conversión automática de tipos. Estas funciones se pueden ver en dos versiones: un tipo particular de constructores y un operador sobrecargado.

12.6.1. Conversión por constructor

Si define un constructor que toma como su único argumento un objeto (o referencia) de otro tipo, ese constructor permite al compilador realizar una conversión automática de tipos. Por ejemplo:

//: C12:AutomaticTypeConversion.cpp
// Type conversion constructor
class One {
public:
  One() {}
};

class Two {
public:
  Two(const One&) {}
};

void f(Two) {}

int main() {
  One one;
  f(one); // Wants a Two, has a One
} ///:~

Listado 12.18. C12/AutomaticTypeConversion.cpp


Cuando el compilador ve que f() es invocada pasando un objeto One, mira en la declaración de f() y ve que requiere un Two. Entonces busca si hay alguna manera de conseguir un Two a partir de un One, encuentra el constructor Two::Two(One) y lo llama. Pasa el objeto Two resultante a f().

En este caso, la conversión automática de tipos le ha salvado del problema de definir dos versiones sobrecargadas de f(). Sin embargo el coste es la llamada oculta al constructor de Two, que puede ser importante si está preocupado por la eficiencia de las llamadas a f(),

Evitar la conversión por constructor

Hay veces en que la conversión automática de tipos vía constructor puede ocasionar problemas. Para desactivarlo, modifique el constructor anteponiéndole la palabra reservada explicit (que sólo funciona con constructores). Así se ha hecho para modificar el constructor de la clase Two en el ejemplo anterior:

//: C12:ExplicitKeyword.cpp
// Using the "explicit" keyword
class One {
public:
  One() {}
};

class Two {
public:
  explicit Two(const One&) {}
};

void f(Two) {}

int main() {
  One one;
//!  f(one); // No auto conversion allowed
  f(Two(one)); // OK -- user performs conversion
} ///:~

Listado 12.19. C12/ExplicitKeyword.cpp


Haciendo el constructor de Two explícito, se le dice al compilador que no realice ninguna conversión automática de tipos usando ese constructor en particular (sí se podrían usar otros constructores no explícitos de esa clase para realizar conversiones automáticas). Si el usuario quiere que ocurra esa conversión, debe escribir el codigo necesario. En el código de arriba, f(Two(one)) crea un objeto temporal de tipo Two a partir de one, justo como el compilador hizo automáticamente en la versión anterior.