Correción Taller III. Lista de Chequeo

El objetivo de este taller era realizar una práctica con los idioms revisados en el libro de Coplien, particularmente el virtual constructor. Se revisan los siguientes items de el código:
 
  1. Que las clases cumplan con la forma canónica (constructor por defecto, constructor por copia, asignación y destructor)
  2. La claridad conceptual de la estructura de clases
  3. Los algoritmos de conversión entre los tipos
  4. El tamano de los objetos
  5. Que corra la aplicación sin errores
Algunos de los defectos encontrados en el código son:

1. El diagrama en Rose que acompaña el código es incompleto.

2. Una constructora como la siguiente

Number(const Number& r, const Number& i);
Permite que se creen números complejos con parte entera compleja...

Operaciones como
 

        virtual Number restaInt (Number& n);
        virtual Number restaLong (Number& n);
        virtual Number restaLargeint (Number& n);
        virtual Number restaComplex (Number& n);
No tienen porque hacer parte de la interfaz pública de la clase handle. Basta con que las subclases las definan y que sea protegida. Además, el tipo del parámetro ya es conoce: en restaInt es Int, en restalong es Long y así sucesivamente...

3. La siguiente operación puede fallar en caso de overflow del tipo int.
 

Number Int::sumaInt(Number& n)
{
 Number retval;
 int temp = valor;
 Int *i2 = (Int*) &n;
 temp += i2->valor;
 Int *i1 = new Int(temp);
 retval.Redefine(i1);
 return retval;
}
Es necesario comprobar que la operación no se salga del rango permitido.

4. La siguiente función de calcular el tamaño de un LargeInt no considera el tamano que se gasta el almacenamiento del mismo número

const long Largeint::Tamano()
{
   long t=0;
   t = sizeof(*this);
   t += valor.Tamano();
   return t;
}
Debe contarse el tamaño de la cadena, por ejemplo  t+= valor.Lenght(); (Suponiendo el valor un objeto String con el método nombrado para calcular el tamaño).

5. No es necesario modelar el tipo del objeto como otro atributo. Pude ser dado por un método redefinido, si se requiere para la visualización. (Por ejemplo un método const char* getTipo( ) redefinido en cada subclase)

6. El constructor por copia, como en el idiom Reference Counting, debe referenciar la representación, no crear una nueva... Por ejemplo:
 

NumberC::NumberC ( const NumberC& n )
{
        switch ( n.tipo )
        {
                INT:
                        rep = new Int ( n.valueI() );
                        tipo = INT;
                        break;
...
}
Debería hacer algo como lo siguiente
 
NumberC::NumberC ( const NumberC& n )
{
  rep = n.rep;
  rep->count++;
}
7. Las clases particulares son responsables de sus operaciones de suma, resta, división y multiplicación con los otros tipos. Una definición como la siguiente es incompleta y deja demasiada responsabilidad al handle
 
class Int : public Simple
{
public:
   Int();
   Int ( Int& n );
   Int& operator= ( Int& n );
   ~Int();
   Int ( const int& n);
   int& valueI();
private:
    int rep;
};
8. El siguiente tipo de operaciones no son válidas dentro de un esquema de un virtual constructor. El objetivo de este idiom es no tratar mediante switch llos tipos de datos sino mediante el mecanismo de sobrecarga de operaciones y métodos
 
Number Integer::operator+(const Number &Num2) {
    switch (Num2.tipo) {
          case INTEGER:
            return new Number(Valor+((Integer *)Num2.rep)->Valor);
          case LONG:
            return new Number(Valor+((Long *)Num2.rep)->Valor);|
          case FLOAT:
            return new Number(Valor+((Float *)Num2.rep)->Valor);
          case DOUBLE:
            return new Number(Valor+((Double *)Num2.rep)->Valor);
          default:
            assert(false && "Operacion Invalida");
    }
}
Algunas de las características encontradas en el código son:

1. Hacer un Makefile para compilar un prgrama con varios fuentes.

Los errores encontrados por cuenta son:
 
01 1, No esta terminado
02 -
03 -
04 -
05 1, 2, 3, 4, 5, no parece funcionar el tamano de los objetos, No hay reducción de tipos
06 -
07 -
08 -
09 1, 5,7, No están implementadas las operaciones, No compila, Constructoras confusas (Complex)
10 (Mismo grupo 9?)
11 -
12 (mismo grupo 5?) 
13 No hay permisos !!
14 No hay permisos !!
15 -
16 -
17 -
18 1, 8, No es claro dentro de qué contexto se requiere un constructor del tipo Number(Number *num), No corre el main pedido.
19 -
20 -
21 1, No se nota la necesidad de operaciones como int_equality en la parte pública de Number, corre con un main distinto al pedido. No hay conteo de referencias
 
 

Ejemplo

A continuación se encuentran las clases de una posible implementación de este problema.