[C con Clase] Tipos definidos por el usuario

Salvador Pozo salvador en conclase.net
Jue Dic 22 10:24:27 CET 2011


Hola:

Pues está clarísimo, Yolmer: no se puede porque no, y porque da error y punto.


:D


Es broma, aunque no sé si podría explicárselo a un niño de cuatro años. :)

Analicemos lo que hace tu primer ejemplo.

Básicamente, creas dos objetos a partir de estructuras anónimas, y luego intentas asignar una de ellas a la otra.

Al compilador no le preocupa que las dos estructuras sean equivalentes. No tiene en cuenta la estructura interna, sencillamente ve un intento de asignación entre objetos de tipos diferentes, para los que no existe ningún operador de cambio de tipo que pueda aplicar de forma implícita. Tampoco encuentra una definición del operador de asignación, ni constructores, ni nada de eso.

El compilador es capaz de asignar algunos objetos de distinto tipo, por ejemplo, un entero y un float, porque existen operadores internos de cambio de tipo, de int a float, de modo que primero hace la conversión y después la asignación. Esto no es posible con estas estructuras.

Pero hay más detalles sutiles en este problema.

Si intentamos compilar tu ejemplo como código C++, debemos tener en cuenta que el compilador creará algunas funciones y operadores para cada estructura. Uno de esos operadores es el de asignación "operator=", por eso el mensaje de error tiene esta forma:

D:\main.cpp|21|error: no match for 'operator=' in 'alumno2 = alumno'|
D:\main.cpp|11|note: candidates are: <anonymous struct>& <anonymous struct>::operator=(const <anonymous struct>&)|

Es decir, el compilador no ha encontrado una definición para el operador de asignación que se ajuste a la expresión del programa, y el candidato es ese galimatías de la nota, que viene a significar que sólo puede asignar a alumno2 un objeto del mismo tipo.

Si lo intentamos en un compilador de C, en el que las estructuras no contienen funciones ni operadores, el mensaje de error es otro:

D:\main.c|16|error: incompatible types in assignment|

C es más claro: tipos incompatibles en la asignación.

Por último, C++ dispone de un mecanismo para identificar tipos, lo puedes ver en el capítulo 42 del curso:
http://c.conclase.net/curso/?cap=042b#inicio

Si aplicamos el operador typeid a tu ejemplo, de este modo:
----8<------
#include <iostream>
#include <typeinfo>

using namespace std;

 struct {
         char nombre[8];
         char  apellido[8];
 } alumno = {"yolmer","rosales"};

 struct {
         char nombre[8];
         char  apellido[8];
 } alumno2 ;

int main()
{
    cout << "alumno:  " << typeid(alumno).name() << endl;
    cout << "alumno2: " << typeid(alumno2).name() << endl;

    return 0;
}
----8<------

La salida es esta:
alumno:  4$_10
alumno2: 4$_11

Indicando que se trata de tipos diferentes. Esto es sólo para verificar que las dos estructuras anónimas definidas son distintas internamente.

En tu segundo ejemplo los dos objetos son del mismo tipo, por lo que todos estos problemas quedan eliminados, y la asignación es posible.

Hay una tercera solución, al menos en C++. Evitar las estructuras anónimas (usando nombres), y sobrecargar el operador de asignación:


----8<------
#include <iostream>
#include <cstring>

using namespace std;

 struct A1 {
         char nombre[8];
         char  apellido[8];
 } alumno = {"yolmer","rosales"};

 struct A2 {
         char nombre[8];
         char  apellido[8];
         A2 &operator=(A1 &a1) {
            strcpy(nombre, a1.nombre);
            strcpy(apellido, a1.apellido);
            return *this;
         }
 } alumno2 ;

int main()
{
    alumno2 = alumno;

    cout << alumno2.nombre << " " << alumno2.apellido;
    return 0;
}
----8<------

Pero no uses este ejemplo si tu alumno tiene cuatro años. :D

Hasta pronto.

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


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