[C con Clase] Buf.....un duda de esas básicas, por falta de unos buenos fundamentos.......

Salvador Pozo salvador en conclase.net
Lun Nov 21 11:48:28 CET 2011


El pasado 2011-11-21 09:58:29, Miguel Angel Torres Fernandez-piñar escribió:
 
MATF> Hola amigos del C++.....

Hola:

MATF> Esta duda es demasiado básica, pero le he dado muchas vueltas y no sé qué
MATF> por qué no funciona :

De básica no tiene nada, reconozco que no es fácil explicar por qué no funciona, aunque sobre todo porque tampoco tengo muy claro qué se supone que debería hacer este programa...

Cuando haces:

Persona("Pepe");

El programa no hace nada, ya que esta sentencia no es una declaración, sino sólo una expresión. El programa evalúa la sentencia, y nada más.

La sentencia es sólo una llamada a un constructor, pero el objeto construido es destruido en la misma sentencia.

En el segundo caso es similar:

char nombre[10] = "Pepe";
Persona( nombre );

Pero eso es aparentemente. Lo que sucede aquí es algo muy sutil...

El compilador considera la línea "Persona(nombre)" como una expresión, pero no tan sencilla.

Primero, considera que invocamos al constructor copia de Persona, pasando como argumento otro objeto de la clase persona, al que hemos llamado "nombre".

Aquí es donde el compilador da un error, porque "nombre" ya está declarado previamente, como un array de caracteres.

Veamos lo que pasa si eliminamos la declaración de "nombre":

----8<------
class Persona {
   public:
     Persona(char *n) { strcpy(nombre, n); }
     const char *LeeNombre() const { return nombre; }
   protected:
     char nombre[30];
};

int main() {
    Persona( nombre );
}
----8<------

Ahora el error es otro:

error: no matching function for call to `Persona::Persona()'|

Es decir, no encuentra el constructor sin argumentos para Persona.

Si declaramos ese constructor:

----8<------
Persona() { strcpy(nombre, "Anonimo"); }
----8<------

¡Veremos que ahora el programa funciona!.

Lo que hace (que es lo que intenta hacer el compilador desde el principio), es crear un objeto "nombre" de la clase Persona, usando el constructor sin argumentos, y luego invoca al constructor copia, usando como argumento el objeto "nombre".

Recuerda que el compilador siempre crea un constructor copia por defecto para cada clase, y tu estabas intentando invocarlo, sin darte cuenta.

Si en lugar de simplemente poner la línea:

Persona(nombre);

Pones algo como:

    char nombre[30] = "Pepe";
    Persona( nombre ).LeeNombre(); 

Verás que sí compila, porque evitamos la ambigüedad, en este caso está claro a qué constructor estamos invocando.

Lo mismo si hacemos esto:

    char nombre[30] = "Pepe";
    Persona( (char *)nombre );  

Espero que haya quedado todo claro, no es fácil explicar estas cosas, que generalmente sólo surgen cuando se hacen cosas raras, como experimentos con lo que acabamos de aprender. :)

Si te sirve de consuelo, reconozco que me ha costado un rato comprender qué estaba pasando. :D

Hasta pronto.

-- 
Salvador Pozo (Administrador)
mailto:salvador en conclase.net


Más información sobre la lista de distribución Cconclase