2009-02-06 5 views
7

Estoy cambiando una rutina anterior que solía tomar un parámetro entero para que ahora tome una referencia constante a un objeto. Esperaba que el compilador me dijera de dónde se llama la función (porque el tipo de parámetro es incorrecto), pero el objeto tiene un constructor que toma un entero, así que en lugar de fallar, el compilador crea un objeto temporal, pasando el entero, y pasa una referencia a eso a la rutina. Código de ejemplo:¿Cómo puedo decirle al compilador que no cree un objeto temporal?

class thing { 
    public: 
    thing(int x) { 
     printf("Creating a thing(%d)\n", x); 
    } 
}; 

class X { 
    public: 
    X(const thing &t) { 
     printf("Creating an X from a thing\n"); 
    } 
}; 


int main(int, char **) { 
    thing a_thing(5); 
    X an_x(6); 
    return 1; 
} 

Quiero la línea X an_x(6) a no compila, porque no hay X constructor que toma un int. Pero sí compilar, y la salida se ve como:

Creating a thing(5) 
Creating a thing(6) 
Creating an X from a thing 

¿Cómo puedo mantener el constructor thing(int), pero no permitir que el objeto temporal?

Respuesta

11

Utilice la palabra clave explicit en el constructor de cosas.

class thing { 
public: 
    explicit thing(int x) { 
     printf("Creating a thing(%d)\n", x); 
    } 
}; 

Esto evitará que el compilador invoque implícitamente el constructor cosa cuando encuentre un número entero.

+0

Ver esta respuesta: http://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-in-c-mean – Skizz

+0

Perfecto - He estado escribiendo código C++ durante unos 15 años, y tengo nunca he oído hablar de la palabra clave explícita. ¡Gracias! –

+0

Pregunta relacionada: ¿puedes usar la palabra clave explícita en un método que no sea un constructor? –

1

La palabra clave explicit funciona perfectamente en mi ejemplo, pero me di cuenta más tarde de que mi código mundo real estaba fallando en un método sobrecargado, no el constructor. (Mi error es hacer una pregunta similar, pero no igual a, mi problema real). Como señaló Mark Ransom en los comentarios sobre la respuesta aceptada, explicit solo funciona en constructores. Se me ocurrió una solución que resolvió mi problema, así que pensé que lo publicaría aquí. Nuevo código de ejemplo:

class thing { 
    public: 
    thing(int x) { 
     printf("Creating a thing(%d)\n", x); 
    } 
}; 

class X { 
    public: 
    void do_something(const thing &t) { 
     printf("Creating an X from a thing\n"); 
    } 
}; 


int main(int, char **) { 
    thing a_thing(5); 
    X an_x; 
    an_x.do_something(6); 
    return 1; 
} 

Este código muestra el mismo resultado que el código original, pero no se puede utilizar explicit para solucionarlo. En su lugar, he añadido un método privado que toma un int:

private: 
    void do_something(int x); 

Ahora, el compilador no crea el objeto temporal, se da un error, ya que estoy tratando de llamar a un método privado de fuera de la clase.

+0

en C++ 1x, podremos escribir void do_something (int x) = delete; ya funciona en gcc svn trunk. –

+0

@Graeme Perrow. Explícito aún debería funcionar en el caso que delineas. Es decir, hacer que el constructor de cosas sea explícito dará como resultado un error de compilación. ¿Es porque no tienes acceso a la clase de cosas para modificarlo? @litb ¿hemos empezado a llamarlo C++ 1x ahora? ¿Me perdí la nota? – zdan

+0

@zdan: tienes razón. Estaba pensando en cómo modificar la clase X y no estaba pensando en modificar la clase de cosas. Eso hace lo que necesito. ¡Gracias! –

Cuestiones relacionadas